From e8896ff75dea2166d8d85c738f6e59cb40b87972 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 16:22:42 -0500 Subject: [PATCH 001/163] create-react-app --- src/FilterLists.Web.V2/.gitignore | 23 +++ src/FilterLists.Web.V2/README.md | 44 ++++++ src/FilterLists.Web.V2/package-lock.json | Bin 0 -> 503543 bytes src/FilterLists.Web.V2/package.json | 36 +++++ src/FilterLists.Web.V2/public/favicon.ico | Bin 0 -> 3870 bytes src/FilterLists.Web.V2/public/index.html | 38 +++++ src/FilterLists.Web.V2/public/manifest.json | 15 ++ src/FilterLists.Web.V2/src/App.css | 33 ++++ src/FilterLists.Web.V2/src/App.test.tsx | 9 ++ src/FilterLists.Web.V2/src/App.tsx | 26 ++++ src/FilterLists.Web.V2/src/index.css | 13 ++ src/FilterLists.Web.V2/src/index.tsx | 12 ++ src/FilterLists.Web.V2/src/logo.svg | 7 + src/FilterLists.Web.V2/src/react-app-env.d.ts | 1 + src/FilterLists.Web.V2/src/serviceWorker.ts | 143 ++++++++++++++++++ src/FilterLists.Web.V2/tsconfig.json | 25 +++ 16 files changed, 425 insertions(+) create mode 100644 src/FilterLists.Web.V2/.gitignore create mode 100644 src/FilterLists.Web.V2/README.md create mode 100644 src/FilterLists.Web.V2/package-lock.json create mode 100644 src/FilterLists.Web.V2/package.json create mode 100644 src/FilterLists.Web.V2/public/favicon.ico create mode 100644 src/FilterLists.Web.V2/public/index.html create mode 100644 src/FilterLists.Web.V2/public/manifest.json create mode 100644 src/FilterLists.Web.V2/src/App.css create mode 100644 src/FilterLists.Web.V2/src/App.test.tsx create mode 100644 src/FilterLists.Web.V2/src/App.tsx create mode 100644 src/FilterLists.Web.V2/src/index.css create mode 100644 src/FilterLists.Web.V2/src/index.tsx create mode 100644 src/FilterLists.Web.V2/src/logo.svg create mode 100644 src/FilterLists.Web.V2/src/react-app-env.d.ts create mode 100644 src/FilterLists.Web.V2/src/serviceWorker.ts create mode 100644 src/FilterLists.Web.V2/tsconfig.json diff --git a/src/FilterLists.Web.V2/.gitignore b/src/FilterLists.Web.V2/.gitignore new file mode 100644 index 000000000..4d29575de --- /dev/null +++ b/src/FilterLists.Web.V2/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/src/FilterLists.Web.V2/README.md b/src/FilterLists.Web.V2/README.md new file mode 100644 index 000000000..897dc8366 --- /dev/null +++ b/src/FilterLists.Web.V2/README.md @@ -0,0 +1,44 @@ +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). + +## Available Scripts + +In the project directory, you can run: + +### `npm start` + +Runs the app in the development mode.
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.
+You will also see any lint errors in the console. + +### `npm test` + +Launches the test runner in the interactive watch mode.
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `npm run build` + +Builds the app for production to the `build` folder.
+It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.
+Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + +### `npm run eject` + +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. + +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. + +## Learn More + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..fe5c5e8b7947e44643fcc9713e0e33571dca23a0 GIT binary patch literal 503543 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 z z?+cQHBVYFV?1hGq;j%(QkSS%Y>Bd-``EvqO`_#5O9F3Q;iT4I$;@BkZ?pi-CTK0q+ zM9p=mG$0$4U`|JOFea@gLNAFiJ{chi4-@0lL~Aav{rddEaRAhJ9VzJ-^dx1A~CK@-nUahXg`W%24aNc;n~maTew z{wyM%uk|$nW>Sf6@Vh|fCo^r(j9N;2qi#e)?t(etCL5a++mKpF`J=!fsEA=_xEIE> zz4xYd3^jOPvv8zq8tB+!<`}exN3~>n+@C5~tGBs6#XG+?^sjpUtD~Cz4*dnj^EER_ z<$vU0Lcc+A2B#gOo9$KL^KRFgYE6qGRlD12*g}J@p~z`A8cy4YPS2Zcf3?^}+>U3K zaPFuUO(Tur`gF6w>m#-o{__|Q|+60#gmJ0E)d3TeNLTs^Lx zA@A{<+%@&BZN6{E|A$J==b6GcJR8)D7g`r2bbTnY}5#6lKKFP9t`D-Zh4J-VmBz{=>{sxz@XEmujr`dh8qZp6~ z<@$KQ9-5q^=?4&05UVKZoUgKS-77Y}4n*nDo#kzXM`l#tk7#B6yjU}T=X~|tto}v? z$vE3Sf-p2KuIA0qQWdp9FA|dkN78b(2qy&YME{GhGc$uG>bJexD|g@ zIiMNbka4>^;Es+$Hrn1XSsCpO27${-Z=pxXp(}Az6YRO#w!0Vf;Sf`oUc1N75t&ki z@j~qH8Jua`NWDqMKGB>j`}xE)PZfM{kar+|M0p}_?*94$R{348xL9_&e&N{y07ZGY zGyfw$P2Y0e6te=!!FYE%TLjX2Zs{i@!JPrke&6<`{HlfMxatWv+IsKMzW?|NfoFI2 zqcr-7JNvRW5Y6SU7ZT{DD;xdT%F||>6larubEny|uxKjO&;aLDrxYN$Jj)9XlV2$U z^w%CgPpl@pqf{n;g%n8g$Dh52N|`n;Pg2RgF0BucDSdiDDfzmelerhDu*A)7V2+c} z9yHy!A9Yg=I1N`C3U_&?chD(iMO;C12SWbak|Q8zIR)pq&{lTGYxsRmOvzU(1xPZV z-u+zVS1SfcE^B9Os7Qaw{ezFED_`#!W*I9wog_9`4)FfSZ~NqWbL>JD3CZIF7c(1+ z7T%Eu1Qm>b(bx;Gy5GuKiXZXk%> zL%e9Z|CE!JJ?~pcJ}0i^FINKPBa6zfRtIIicmc~IfhAwRBcE_a=b(g1k4~}~}N)h0wKw6Ju3!b4-2*oFKR63M-K1B|SEc+o} zrwSa>o+33mwGBF4tj7p+g7K$1(VM1N_v%u~9`TCZ;@_LQ=v~FpW3;ETW|Id}YA!TTWQU>Q&4fAWH<;yi;v`DL9#H3i=_qO|U9V@giQb=poStUscOw+Jq#PNLAI>quypLj`)YZ!x&QQHcia`Tbe9!L#h zI9g#k+fMg^gf028xuJt}fbK$usbIZA2?{*)w`!f^hnXCG+sQe@d*c^Cyseu7@Ae@- z1dR$%8&d)lU=7a}Mm3e=Otjp=Tpv?jGm^K#5S!{4zYK=8nT9P+4dpCCb5dto>uzms z%Oq9diWq4*JRftR;8HP&GrN{e z^h|yd`@gPwrQc`nlMQ+4KMR9O+$Ucdpr8K>Y5=VBK&|;s&s;b=#p19#Hhmd~%)pH} z*woOm6LKey55%S-neABbV30C_;q*=-oY?J1r@+88 z(gJ!buF4df@BCh*S$SZz5JKN_@BHTX!27K}W!+{w!V2Gm4gFv=J@VCfaI#`|Aoo>k zI%yfoh%tNG#cPng^&6(`1bPB>G?4rwWzk^?iksf|q0Zc`zd4XE_sCD@%PZ9ag#*PO zAVw(k6UP$=5Z>$>7;;jzk@v~51KoU~q6-em6al?!HMK&ff$Y5G&sdHPfYPsf2^iMQV!-LGu%-7*+8Mmwo0Z5;pz>3 z6fWn@bI{!ch}((j!`MGq{VEN$0n6s`!bP4&!v{{}gA1=nl+7BSmFr)D%LI{|anb;$ zgqitlt!(Za@aLbfn}Gg6AHd`RZ5do1zJST8&$`uH*mw$Rs8DzY zv&lS!pbi~&+-PYVcDo)k!G4wu(d9fr5SB1UeLe1SJUKOZ!r+K*0!7VJNMn`UoP z_ML5AGi-)+Yw-_^jjRikY6^uE{K|5>`U>)YZ@Ou5SYZY*^js3N$)Z`(Ll)VD`b0g{ zPw!l*zx2v|yIqNGynm*uzPx3FTVT!8q_t5(nVyFSl2Pbdm(!{9${|+EC6{bi)^*qG zO_y+l^LUW9+QFf*JmEc48Ip#IN$Qa!q3vuqlt@G2X}4FFny-z(zuX&N{p(*D^LvO; zTrNU6k_n9{Aw?;VG3E`?p`U*y9Iu$VQuY^fT7bPmi@*{Cf94y%w;PM40UyO5Rh<@@ zwz3L_gDHCMn;Y3#BlF#ANnv}8ViG3A(PqEROtbEGQbQx;BZ(e}kxj~RlRFH$=pG+p zdlW{94(bv#%0fo=z9V|hc*niv7w-Z3j&T%VzJfOgSw&|0X0H;}KA|-)=&qoxWMGSH z=jFJKAGFR=Klf_jy4a5gaTp&{&sA+J&~4UWwT{Gfx%rxaVa(cTTn9&VJvxwBP@iY|#u+1$;n72G@RanwH|>+{p%~soHO!u{^C_|xcC_t6 z6uRVfs?2P@1aFqtR^k_*6uz5X^HY#!3zxu{eJnJ;?-f6X^^&^P3B?xC#HX^QtSAZ5 z`{=@TMJ|}|3wc&gR%>t3V^AMA&;G)sW#@SAIp-a_WE3Nnw?rpu%w;)oCEeH>jY*!= zcRk{7KnDc>0R#(83mhACEzt8Xq+8bJfv7K3lV8mE`9oXVD@i>a{QTye(R}z)De8D% z?jvtER%ZWM>->9m?(N~DSqOCocE>;M?b=46hb@S$&-x#Mj*rrN%HzEYnW6sT> zI~^sf(A#jG8rkcjrcNYKqp*v6&ai{7r?m|wqyguesAyLRN&gq{&JgBJ1jt3M6yAZ{ zg$6!MFr98f_AU*+7A}8)rGt`u2&Q|;I$2!BL|N)*sQN_;|HE;;?ePg;w<|f)9=krh zMA~N3nvN8+=QWQcyI$ObQdRuxew3kCnFa9W^1 z@5X4}pdvHh{}dJFZ9ZY6d@)b#sDKb|(}I>cNu(wM6P}q4Zym;=R6_)soi*h;zI1I) zO+5M(^BWOA>^-+9Qe4wki8HaCEH$jfQUW&UHP+)6W31N;cPKMutKw%)>sP@b_@Fsux5UD9!cZNOe4%#YFFX;=@B@5Ve@*LRYr! zU`w{#P;7{ebuZRVSd+rBK%Ul&z;0l?D8@=Qp3tUMX-F(2N>vbZoPr1a$0zC^MhW!B zdvlC3-_#!-BUt$0^DH)gBlaTdNf zdi`Xw=bCP<<=NZwaHbIcQQ02i&FtJ4$)@Ghk(4GAJ|LzZ6ifF21s5%C4-Jmi|>b7RT}nWd4bMmm78$zWspG@`b8L zX`u(QgQnf?VmGYgmR(=7J7l52 z&bH%QUKOpVrZ9aqd z{st61#6_M;pw2A135sHdSnUW#3wp4 zhfa|m*;=%9GZ}AX6TwI5a@`&f4u>fZf#x^T{+Yr{fyX~qzY0KIE%SE{#jMu+E~0)( z=eJEhBja`nG~p~y<=ZTk5j7nhJl!68tY=cKZFezEmgt&FB^fnSInr?Sn6~sSyP3(@ zR(H-RB=O5peb#ik9gJOr7qLhv71+RgfajsJH{Ago*3hlvUxIx9i>^ z@hV^b6T&zvOBo0K@t^QEc|lcsC69IrQnPMbWq zoVXe=a9`g9%}u@Q)t37XXtlI?oXi@mHKjj(_1Y31--rn+kb+l;BAC5AZRAx%ije}Gt2lc&VQ=o zJa6*AaUS>24XO${&K8eCqS5Z_(N=BF_uVO~?TZcUf;de)m*0gKtE-atfXsc~#k z+mzm6Fw2jVMOukbh z{}}+^w|N2L`^Bn2<_S{WqS}TS=q!KG#>7M&YbI3OK&&*b?~~OLR~ReqDU%w`W8!Mm zHQWx27@2zbfMxhi1KW%1bGT4N=ncGbkz-HlIKQ%5zqFgKKvpa_d>2>9;QM=%>0yT# zpv`x#>I=a7mQJ6=vwavDv}&AmSDit^<$e*%^_5XW)MYzB$@RJ3i6d2ubhE}D6sN_y zYg=j&-h#u1gy)UVS#M8agUw-%O;Z1bu&hYB4g|P;U6z%vyk>t6+WR&y;CsJV707dr zYl!2~sH>su3Z0L}0puJah(6|q$-vsQoe?!zG0@VSIniD1P%~SqWk~wcn`*Hk?_F{( zi}m3_X)tWPPOe3&U6bg41AlNL5&D^fg>^2(!+?ZwF+JaEv|83sty1CtY<<4WwfL1IU$IZ$1z@sZ&hO=8d4m!v%3tRp z;|g-oj|HiPMG&r}m7S<#UZ;LQ67XoTT&wA=gZbFEwY|_XyQ{Fa6(}g;CozL%rnH33 zA~!uAMRT?q`Pk&pte>R=w-MI6Uoe+DFiN)nub{7*N&>|ikgTdh4%r)v=y9aTPtV2U z79|WkUI5;coxgAWFNTjUX9;3r(Ejg+% zFh>ouwn4OHFPS)WkqzGk7W5XbWuN|! z;ac9I4A%1ZIY+MmRlYqu?yUopHj8RwFf4#ohe!`8pjh_b9`g|yJ*yx%18m#SPu_x!%UA6l-~ih*x(aP zi?6Ge-tX&!O{Dh>Qo$DDaLPyWzS$istD!Mcm}H^poI0P6ogOA1+LVj+g9MznbFW8@ zqcc?}Tij%APP^mHBr-)Yi46DXGmT#{i*G;*ZE8<~uM2k84)|3rLZ;r`V;esQ>3xF- zklw$pN~NnFHsKcQ)6kzcggJd433B(ik64zr>fB)}Z~A0!CfF9y8c)!fC20Y=ShRg= zmYN}A?r^1-E}<`4ydTVDN^-{fJUNHI&^zv9$zIweP?nK34uSqJ;rlp4k$1O@=eY{XLOP1s*ZzQZVb~uY>^!U6AsK!ENMr*IjPxPZr0r7$7sbg4~wAgLv z2+CEFQ#5WvZO^H`A5gXC>EN5*0fxG`z8#V3+4|=Jt6PGmK$>6poyL$cf!}M*pSLLi z`18e_Ayh~>b2hXzndokN$)`OIi4UREN0m@hX6+>nj;g4qDhU(#D=+)x*)& z+I@A__LeL)+z`EE%kH;aba?hvr9EFC7yq-`1B_jTks0s0kp3YOinYs-FTSY??s2)Y%Tw zVNQz)yHnPpFmrKdUM1XbIOD1g!;&&up zWIX+rpOiN!fxP^6)x661uuRdp!o&2Zrpn14If+J?+8ac1&6`AwJv{7zjabO;Fxz{? zj8AG8lv#l4)c`e#7KhH62%;z#;r}%i2|kqFZth+nPfUb=JB&tJ*)nDB~Kq) zy8Kk0mewz0>b@%=s*)z%a+xNMGn=Ih4S*s=XBe!eP1XaUJKal-HcLt?x7Xp7%>|{gP6urH+3hy3JxgA2`v2vpuaBVRaeS|!=YPQ z_2!2ZmxpUPW*5MO7_OTJD|Em}{?L)aSq$*~fHCo(HTN zGz@=XfZGX~krPR3i|q*UyMoZ_qOoiZ4_2(&r*6`Sdab%Hgh;H{O|or^Ta7yIDwr#m zr-YG4<~4x`h~g_2^y(sv?kN-V=L)310_mVw!bf?ZZ!?Tc=u`%UC~r>3pQ0;Y`vG71 zH&qdaQoDtWON~>sT3gCI^rjIZ3~NMhb;kCS{rEVrxAxMVa0VJqrvlWMrVJJt>NeB} zp`o$cT4#Hl?sTlNZZp=QJ8o<(y#m6XJuKhon0ao{2V}olLe@+D6`T1pwY|JS37X}v ztE%m))3=;d=y)*f&k!dA&g^%+#k#MhzS8tg;>td*d4-S7VBcXmm*~mQJfdk72rzpv=Ur z+QGXJ6+mNX9Yd)^h-z|%76{)dV5AU4Az_EW>P<7LBUNV^6YgJBHc|86g z4T3N=m4hH13qDp*^_SA10J0yMUwE|sBp0=`{wECPyXNStkdeCULJA^Ei6`#7uH$}l zM-pV}oacqQ`;ru1B`fmFCaelo0XxVt#-t1O$v;+gW$k_IB4lZ`69Lw&73c zl7lnr`g^N0A9T(~_UOYvyzNODjU!Uirk(KQq&?m5@v*T?meEutjzfM-PP=EpuFb^X zIHX>lr#GziYt~tyrproo#%My z#4~dxP`a}?E8>8qrY#*059WT@*Qx#4CMC9|b~@U8&$e1yYS3$;GkRt;<3+6kCw*Xp z8aSo|UyH5<^4D?0_apfi3=t^ACM0;5TaJ}(c~%7fY1{&z79M&*mCMfl5yTcde8y_= zeN~iByUIR2kCS?`Y=QZMVR(YC&#m5huwWYdX;bId9&>;mB1m6T6xBjDNjq{-^=!_f z+GuUiHLJd|^mEfVl4oY7bmC;Nui!_>tMcr~`Ut=X&DrB)To_nm1^HPPj}_?RPmo@s zovhD8AsY+#a+R}w6+_wYu43>XCyCo8pQ++@sVZTN+7zlYx@oYO(Lbst>9n{g+}pSn zTRrA94|eEOVezRx?Hj$}Ty?FzZ|QQTVssowq*=3>5<>KkZdM zcCVkNYN%)_aLW-vwWw*2Z0`qqZ;os7Y=irwk&i4--EP}oVUwMx8T7ehG+XBGY!8Mr zN#5>#XLDi)#HPU*-IQ3gyC=7=OuX}QUqRA7bI5n&MlTi6S2$!1p3M(2{g4$^h|G5( z&J5_km`wA{W-p-r{5(0>D@?I*mOG}+5l3Z?3H6jTyJOByR$AI3I<}KoddyRyFvfS3 z(nvNdNhYM;-onU;942UQ)^-C;Oco zsxIaJDmklrZiIHlCNyb(JD29qyy_1-yue$&b5+lJAKe;mP{(a6++lSoGEAwrm@kF_ z&hCwKluQ*GsgVu6F=H2e*T#0rq|cEw&(p+d#yAA{76;)WFzo3v^hUdJeeHJpzwjac z5Ls6#^Cb$3G^01V!au{iiY;Csp}0_$Q!Vr^&I?^tMTzEkzA`uVl;+jl3W6DvNvx9_ zo1xfY-?Htd;hcwCjGHGqFSlALzGfN&D56_CEpMXsg1S6JYG$lVyHzT+^vpTtD-ivI z9+g3AiO_T6qDOw?g717?!f3<5QQdwQRmv(t@2-lU8pxNmOF+MTQ?*;v1m=2fL@0B! zBgU&!s@mN*d|PT#)?D%=Nl zj2Q4u@~}MR-Q{jN&r3o7sSDIMesepU|6}UscR5*q2*vB_WjJ2Hs|rbC?V@VzPivhc z!|t8#rcXhrdd7ChlkOxi;pM@dTjzd`jB2A=8DOZ%%1&&Lvcf0)^Zqjd5PA`wcLDp^xwTq;nh~`(D%*#p)+lCclE=hc_L2R zX55>jK_gyc^W|yK>*@q6Y)%y6v?G47;sSo!WsTuZMIm=A+NkNWMdRICjhgaHsXwS< zzC0^X-y|^JAq@HXz{}E0wf+}?{=G-&-DWT0{rEgpt;Xi0VMu|n+IMSAxLplA6=_;6 zX)`%&M$PeLs}TX(i)zQFN#nT5C|$YEZPqntE#x_kMC)<-)*Z3<93rv<7-fqms{pjC z?`v8gP)weZ$A!+S>u!8|=J8m^Mdnr2_ zhLTVBa9^&VQGLSRH~zgpa{&AqYC+|Ix#b^uyzJk6O3PclL~!|rsyOyex+Zhn%B3P_ z5;W%lqPFdsyj|i1GN%XKLo|1WDHP`rxYFO8HrDb$ELTyNq>YUn+Kk#+OB}auQ!~d- zS~XR~$LPPqhx>^p{%22g06n7LDuw^laV|D_iR$7~RU~iy@z#<1-4XCruhriZ=bqgon*^Xep^KSct*uY8_@X z-{W3yl$-y_gBj`&VbX31eE)9N`@G#ttUcdU6@P*h<6OV3$eV7bq10;i`uO1Wm#u&w zj-~Y`6=ty`OxA~aydREK{n&wd7y(Bl(os=5ZG5&|oFjswtbv@wqsB0jQNG=(fWQA` zhYlR=lJj=T^gpF_UUqqjz{|B9ZxysoM@D-)uMrP9yLRFcZ@5;X@H8{9wqe1{S0~vD zD}{*Ey1i#+!lplqgm#BaSCft!Agu|tvzd8ZA7YzeS6{T2HnxemxPsIC`%uYez4V2h z@Mn@S^4}$!{bQK&&DU7+&8ir3+YTd4TDAEsj=GGy5^RK`T+8JW315ZBsq1oToe||( z8|xg19!FSAiZ3IsKe3i14JA;jptZ-;ZZ{iwtJ*=)<@&D5_#+5OUPr)x6o7h>=66@@ zuD5*3%=o{6$M~Q_k+%zem4CB-bKmGCR_~XqvdwVaBj=hQ%$sh%?f2BwTQIdqU6|DD z&_AqjZ!q-4Q-eL)k?M^{htWyYB6f;lUK021fOOcsTKCqT>z?%mzJMaa*7P@Zn^irs z<;0qo?m)+ftXM_<&M5qo=1q@Vlo0WF0Z>q>aZ^JbuEj%pC)mk}N)*-)m!TOm^Z`4~ z?9PgmqSi4W=tdX_Ok<*TJKM&P>G$^Cn4nCy)<)b(JWhpCyjU)sG1HBdh4vb#*57hZvFc3~21f9Rl!! zjZeL0$l2I@%aNnD-i?t35>tJtQL7Wwwu3d-%qnW9^#caIaHQ4LP<#i2=mah(M7Mq>3;^?`|>5A-oLC0%<$;al)rSNTe|hk-&EQX0odd=8(X982O}+GCKp^S}E>hHp=aNZ)f$-g9^@& zp8_*;p}&FSpGofAIbQ~0?yS$(e8|9i>A~a0j+hRq9Y7GZ^DybgpZswCw zXT~0u>Ykk|@nFC1Db{*%u8~xb2s>WvkKEo&oV1TSwbt6F$ROD^n@(-Hb=E!69Pfv- z@KEQ2;j)75Aw-a@LH58cAcqXu6k1U-!`lP(FhCTK7K<6;PHvkw3Dn-5EY zxcCrF!9HGkmE|{s6ZfxYE$b|+)+qLW&TRb)?v}-Tx7O2u z;7_jn*Il^ZPlmdzT6V>kVgN-#-0Rr_g(`aY;D7oVWC~_oXhS73iY|A4Fs>_Z{(U;oNF zhCa~C?KMC5)69TUR=`Tn{oIT029^6EFW>#HZAt#KPw8>jM=H12$nVT#-%GGRcT0GY zIeA_5sRh7am+|s1IN>Fy_*&Wi#hQ;r)3--`35(D5zxn+cg}fxwdyVWDk6Ny?ylww- zxqI!@7t584bn@jg!S?cP?jhx(4)x_tpEbJMGrqk4u8(|k-$lF^n0fiS<$jGHf}O(H zal04_`8L1g8hO7xb?gg8s_i?I^`5_ydvc3%md{SzHWY^?&`EbxLEHb{V|~@--xkOHAlUS!)VKf+vWD$IgPvq#+E}v0% ze}bwG&+(YiHI!_Scx$|LadyRTdra6Kkx37+oSHn{Q`_!o&w7$0HZ*dXlG6Zs^l{R3 zF`(HKd0uVo&WIw=6HRo}Nupcwd{Dtg1}o-XmzWh^d=Z@e0h(T@m%j-~ywgoy9mYp( z<>!a7$Ul70f*uh2;(FB@`3BuSNaNYSAJHAQU+c>ZwIOAvOU};I7Q2wl3ElH|ZTgIF zMnrcz-_qi`FSTTUH>cK&Vl9n&Q&7%SI2&#o1IQ2Tu}k+?YQUGrClJ)UEVWPuUcva! zoJghhOOP#nn;(`6!MTJFCWB_g_Ezg=I*^5Wlk}%eWUQe}NL}5ihN0HGr=x z+6T>iIw1RF)JJ1ftWHbSv}On%^I58VO?_#DLMHP zwg~k_SdWI2+5uXitWh;RwXxOQ+AjKaY9-d>cxS8PRIV8nSPca60US9OdDI*3Uc4KN zx%1}x#UhUTx$v;0_guhTc&@*Z6j>c=ly&Me6)7y*HM~R9-R<+!1M|E|31!chstV#7 zF4&CVr%R_##=NocEnGX!TNArSVcK@x*+Z`dT< zZw;SetiC@b4!kT|NRM(WXss1$j-Op14_M6Jw@B2lkURgRxV}P6G4lF~{GTGGyg>;m z<*z~0%mNVKhJ4&PHSTl>Ifi&9HSnO%*qyn|7(AO}`JJuJ>;Ld4*q5LBp-dD^>hF(nX z4Bo6!%6-?$^m$u0gZ%9S^j`lqfdu`S^DB?R`^xTw@ZL~Gr8Tx}>mJ)M$!BWvl`u@9 z=JfqQiuOZpt8y0BZVSB>r+Z1AG zZv;6{NB!QF@XiN-@Us?p*|f&L{yXb~^;(NB;F7s=gm)E7jn>}~*>i`N>id^ENf?SvJf0x+DNq&DrD%X@_2s_|C~ZW-)V;)Bo`3+*1rL}GMU|S8 zb-Q~J%FD0kr4NN1Y{D$RI}~97NXf}c?~AKw2Y`G>(oN9GP(lGnwx!3u&CmN^2|8;) z@YpKjvA{FmHgL?7lGDr~4Bg=WLlAfk9kS-rzirntg1;SKL+-B!xVwJUr|KZx)WdZBb=|AzjXdr z_R`r(U%xi`A)V*($RROKY#43Vk!SqWMwjuv$IU-6=3-$RT2biIG3!?JPQ?CF&+$KR zPF{e5r zv*$6Fo}h8QIG%L&b|ZBIiC#eR>||o2!V8h*XpoTf6*PVk8S#rn3kc-v=Wksh`qAC! zvv6se?WJrl=BpU3*XOlfg0tJUwr`N}o;%VV9X|vcSiE>O7Q*sr67K$n!0v)C%iLeeOC&8aPV_DT^BEb?)p_e zALv`{#u`hGwCw2`z3iRjgEMxca2#v~3k9^BPl$KJ_tajNV?TKfSo8Aq@K>&qeZ##n zt)rH-Y3HnYoVqy$U*Rp$R=bYHua?P~X&Bl?A z!~R5C!rUp4c^gFP`D?$Q)~0F&JLYIAQIXJ>>CSgb2eBQ1fL5}wThab9!|OYj2Ml`n zxN0u1!~xp=yIWfP2hhB%TLAR(;iFjYYmtxvwMUZrQ3eeS*+MU4e~wd8$fJQZ<7jE= zZujH0IkV5wer92uzn<>WU=dS+KkW6fp*}I1LlK;Xh|Nx9TyfWo&!N-dtb+H|bR0PH zkopB}9dlI;G8Z2;F-J7OEA$}*fv#m^&oXVUYz*XD)3dUMzSF3kB>fO%`MsS{|NB0y z>IcBTEL#Bo@*!v5?eAe9BHe8=g9*?b2@f}QcRTF_7UlOzT$c}6t$Adl`a)xEamuZL z&)K_VOSX{ZNLJS|KVGHtLlc}9VsFDX!cmxIxzY-^mKR!)OXPQEq}}Vr~7_2E>=h4E!DvwKDkvA=ZH|_vp-`Ev_IpXxmfV7 zt_%I0fgR*kT!9G>TFIOiPBS@hXX{$uC+VelLbvPMYQrfT1m>d*oy1WM#)gSBV_GE- zH11nieP)iFeQm50$hJ1DV|+~;Zw0YWaCLJ-H0XqQp_{-MJ6(b^CHblQPW1dTcjIB{ zjMyK($o-}jw3RdC3O#4RQ|Gowujt9plu(si+i5yJyJp)tyE=-sIq8J?vU6A&vxct* zSeUX>L`1O>jOHw`A#>6o+7lD!4%+0!wk*u5tgT+XN9PG;q*_nLp z9EhweP4Sfod35PlW@4~lj#1048rWaPd|Gpx)FePRX(%HGCxxxpJ+=BXof~>`e``u@ zo{^7rrq<)mr;f30W9G3*Z>`M|Rl`o7PB!)Vil5@O{bsUjz@)n>ky0?aKO7ZW7XU)6 z98jN7;Xowya^-!yFnHra?7V^^3PV_ap_~7TJ{PGI;+)Ytx zr2S}4=2xpW(k_v4zRCmW^Oat?L;Ps7BDP1OxteWIX^%_&_1>@1NHW^gjRVUKmntq{ z5!-GZ4(c4U1=1SqR_aKawnnS=Znei!OoV)ZK1sO;t7(Lz#r#-KAG^H6yXKSMlXSko zYqHKRUA-;$zn;RNk)3`~gPyxXf9^)SESi&hv3{<_e`9)N3Mab_wuY?MjJ9RgQlv9o zz}N=SpCCQA!D&Jr--NP9&$$Mxw4DQF2K57BgyYK%bb+i96z2NONjb?ZpNh88kWRhz zSgwDvSiLta@^^>ZgZK2R9BA}IHI~hNecT$mGje;FC8vZWtzai`3~TNzc^xR+T}UI0;l`1J$rzx03+ZGOOlGMV7kqz1LC-Ilu>b-cl$kHq##CMCn` z)4ZXaPVAZ5IbBh;;yxM(-pV*nsYc@UQN)pnhP+4iYqRT-Gh#ITjD|?@)1vdo8-##C zRg$HZU-rIk_SW}L;0wzRf7uiI>Gjc%K(oe2ZQaG?+7N~V?%Q=~u%8{M2~1#lG=R%X zD?#&%m-xBJcv}1EMPRr5WxhF5=!YF}szOqn%wm0EH<_5H2B{p;WM)5G^Q8^ni@)D7 zgvX^HUnLWU6{0Q~bBMd@GMR6OTe`dJkx{#8kTwp17>=I{+m_u%+vsAYO1Qa322c>! z-6tY62gFa?HNEK2YuoK^RA*pmh{x*0Y+kGPjIH{KDt$qHgUBWrp+83?tOsul{|Egk zvr)gKzU(zAuQlAa$V0rIjeC(~ckpIw<%RrE*-thNfutC$y)+vy2b1)b@Yn*Js1 zRNZ`UdY0$lRAqbx=(1&Rkjp;g7IW)+!s~TSN!<2otAn(cb~;(>E46K$^j7J%vFUnt zh_+LEXNp#n-XW?XYUkE8IH}ZbL@QP}9EJ?^pJ+in{lrW+1byg>7`?3EJ1t@SLUd(! z3n-L7gDlj}7ddWkj&T;J|IIPBZwnXDy?q4uW~Bb@!Ja{&B&j*R=cJl#9VX&Jn2kG9 zqu;@6GkQR>P6A;DjfmXs+Onqj)=AImv?)o0lj03AKlYJEnviXbk&!8Fwgqh+Q=ftm zz7T(ij-2_;ULVS`C#^bV6^rI?Ui=BiF>@Du`_`@Xxi{L)WBKF=ZEuAuW}-s_5=6)6 zdaJ%}OH&4o3C?XFPW-0F6Lq>~=)`eZCl!|sYGcSzX7Qfxjz^9@>(*0hhi{q{j^oXs z&T@nv4Du|5`jN-`FHWqoYc;cOV6NZ^iUf-yYdDC1H(EC(7_LXQtLGi0|H@oh_alDe zbnhd;*N3`dCRg7}7S8jt!fqAWX1+3@C;t~jP4;MI+~hmGvT@Erv^0EmIISfxQ%3NX z4$~8t49gPJVGH-nWHO9GYP278RNSYX1|OZ49PRO4VTLVvYPEJ;@f@FeYAxm^=BzUG zyfL~_W!VUMG(GZI`Wqt6L+kg((^X-RFPV{O9;PoAc>uyEZ7-9z?yw%Mj)$c%vrv?$ z@ZC~fV;<8A=ln70b@}B<6iF_!2|XDMPKG_K1vWm^>MY6HeP$knArnASGBQJy_^btT zTTK>h1-AFX$^AsA6`b5zW%n&|0GU*6FxBtoLB>0wT0ff{P`Hl3oeReN8-bofO>klE zv}2~<2&Z2#&`-k3$t9AEh;yx*Be?G6Wk z^(TCNib(*vF0szaF*BoB?Qx4RIvMf&K6!8=CIrKCB#-52%h0LKs7f zK;_aKw($5}mA4AqDNBv{ywf{g_2~ifXRVZ}@?xW$7(Q*EWiMn|IF&dVh0x@H$Jez{ z)9NP*f$r&fPhKuCOy6oO20eLC;@%k2Ff*7p`s34V(XCI^b{z>hqk$vp3FA6=IAP*# zB%EhNW87W!v73GH4JU)y5U1M&(<{izhWlgp>mRYS``Wi7bKC7BU-tn(ueqEpC@Tl% z8!2W_;N9ei?qOUq)C(o6W;l+yQ(!<_zxKAP5s7giP$6<+Sz3DU~heOfZ4~laF5yr zY@gOFq@&o;(0QP{;^!)MR;U6DAI4EE$d6847eLw|| zAP*erXaJH-{W78QF+2!(%t*wAb_qqiKXbG_AS8r*sgF<)%?ta^F8_czzdA@)KJ%t-u$Isx-#-Bmp3^; zrp-0m=Gva*0`)RS2M768KmxGt$&)1o^%=;Sa4#dcI*{+n19a~n{+A_cmf-Qkg5Qzd zGiR<2k@5xrlk!J^O2!o`X#oDfNLu~Ya%Ff6d$l=Cj?vOux;=akJ)fQ4U_?)qfw=aB zNsS$zxTUY~{nIN%d#TBIj?Ji{Me7s0oI=>hS4=_3Fcd)EXeZv?M#G1!GR(`X$e<70*!DZrJ#+KwsJku>XuJLiVTO#oRzexy@V8@~9dxAGcH3WIYr)?( z_tDavoXxp97|(UA)rJ&CiW20N*4=yS1G-v_4a1hzXx3I@R@RgKF!7*w`*cm7H;R6K zXlk0n?me5xk6$6<3!pwHedoWwsTkl9ebh0E%cc&kwtN`&nB(Qq@tNHL-~_?(5$keT zWC=V=v-}ni5Q=YuTvucrwEcXoOj{^R%KS!E*CJr(m(3o9bbf>B$k%)XU{hU40WLW( z@;j^uk`_Q>U1H_1#zP0O{2s72Aa5bHrOQT-0m0$arX98p% z`FFlw$E#-e^~Y%-9Jm|>U4i!9w`6*0g7lc+*YFfQM3(EZ6RV_ zuv*M{(^p~sY^3#8v!i6YM$l$pJ^{KJ9BS5}S>M%1v=gc$zAiU*y8!wZS{rM%!aMtJ zx49AqO}u7``u+zZ@-BLE1Q!DBwQ#&DD*3<* z)fqzdxT$zP!FKh*sOGYYi1V=@mw^hZ)C>Oq*Z)p;&a-;_3Qbvqzq`U*RZ}c5^RWI6 zUk~5HiO7`c@`-q9p|U7fs~g)^cW#Xs9~%0L9j32LkM)@ybya3RRc0i$W@jogY`BxY z)QQrjrl>t~r$jq_ZxUi%ulMHmh8nj8WPzWFbBtyd>I<69OL$(v;*UsH&!X%FT)-Hr zO0dH2*n|!Rd_&w)%w!^p3PZK@nn`SUzlrQuZG&#$ZO7U%40=9G0csBfwQ06dDIByX zlhbf39{gEdln23fOUm*D=Qp_oeDU6a1SZPcle0+BE|b%1$W-f-tjMv3Fuo|5|w}b7gVhK$i*Vhxa70e|JQ%zdD}T$Ka>Dk z3x-JX&x8FAu7`(ZKmX_!vjV&O>F(Txa#=ikhRiH~G){{}vMW&Q55{wtS?aC;vnyYCLNdMbaanNi++QoxyvnN1Uox2Uc|+pAGM)6{ zm&GL*sOv%kX7*5^*gf7+;PLXjaGW20enB$Cia;BCdig9c_V5^&n;##vtl@*3DI=W= z&3t4n)-w{x_HO*$e!bcSS$71%+rNIu%biA$dTlx0PEmp$NBaZ=fOTEk)E;f65Q#DXd;BLv62IQ2)6#ViKTILH9 z$$($~5S37Pq;MT-GD97Ts=-a4b;M0_IDGQP0q2hMl<=%B{ZU)}>w3W8d;wg_Z<$@m z3l_kjvtS;7EoSe5LX|65SPH-xXT}^7BOtg(v^B zN`gFO(6sF)<%QoKm(@_}OIwJnVgB0Ai-Cvw_4bSLSW z>5Q=sXEOB^Kk+0nc*xL(H+g04mEt*{n}=U%qY6~Bc);Bc^9r&V)_!H4$)&X~&@Fuf z`8!#Z>RYocB*Vp^zn>2d*rZuwmV-b^S01lm#=bt7;ZCv+Igi@$1fB@d*tZ}sZ#5=+ zG_BzXH|Wbde=uzJ=d@y&{Qdv~z=Zg?sGynWf%dE)#z)a_;lF`5K61x$6+&Kj`@q!n zK=3bp{XhQ{#D7+N|52_b&#;v*^B`HDa?k!dGiD#ySLXV$wf`e4S(qf})v(>uJ^5=u zRuDv@iY^C#<&X5H9x)>yh*D(?`87S18R$<=TDItg5VAjk0$`=@DFB6L9X+qcXcIn7 zVjr(j%zPajYKt`9PhB}^611lu^@TfH@q0?L23)$BYu<5P8*ER+9#>g~-J<8@3@JmC zR@54%v(BkP=orQ_NQxSnA8MgmW(vfEBl9myhY0VzF=CeWRO*?KOJAXU3i1P)36(eH zQvi80=ZUtESs`x_kfHZZBR@budF=uZPKB_r`~4`gg=8*rBo=X0&EEzWgS8*B{w zd}yUxWNEX`DUO`};gn8KN%PRN*;WnFm%MALyS)HjLvPf>WP56F+P1Nt7{^__IiHLQ z4z7%d|1J_(u7yFxk$fXDJ_lXjQS)8ns1D4h)pKw@eV5bsV;JJ446(OEY2T-eE)nsu z&|puqzU1_Xjl%A*1Hb7Gw+lSn)g-F3*+XZ6;e6uE+qzgMXq5LwBHB3Hw4R#jP}nVd zQ~l6dQt6~Z>3F8J--tI8zV~J_Pp+FwUd(%f1nGOz0jk6Bx@-=->jxmiOqPF3hUm0o z;LK?6hjo9^?;kPaG!D-?PYmb7L3EmLj+DNe%*lk=)H~ZD<9bcm8aWL|?+h@P6Gogs zZ~aae8y}WE=s~NEd46%r8@#)iZ_fq&>GDW4kRYV0hmYNL%5LZ0FVE)}J3T_^^OHb( zib`j9IpxnsEnITlKFoAlTD_55$C#x|n)~_ijM?}Z(cS${bJ~3m6Zjf73%xeFX?SSF z@TTjoqTPUQcBv5z+46RxLGQ8dLr@%$|4LoCC0rFsV^L23=Gg0lb2o3mt zPj>eW%Fw-kTjYLKC>*v02%el9Qxf952LwT;-DQ*QECq5mSh)@JB%;u(G!AxK1!35D z)L~Yt4~<@kh=`kl);l$h94e3q0G%T2Zhzg!cilA8P+p%xc*0vN^EVO#Km)?+k3e(V z;t4pn?=$dZ67k!Es+vrsDD}p$IazGyl$ab?vu{n$vbf(dGbq(YsTE{t7|C&hp@{Ce z_+j9ayVEvVuQy`}>4yWItz!b&=uPk$3gv5hKvfXm?yaZOU;lz<1s(P+!6i^|@~$R5 zJ6FFE5YXi-TlE6I{O>%sw1PmuJJiV7X`_TR+C&uC>rkE~qnJQyvweEp_NL=yEQNU2 zlD&hJrf4#jTGVzj+p(vFb~_!E6PU%oP@&6qUmAK;C$yW53KBMp|3aEr0Qqd-|I3w? zOf1~r9yFR-l0x+p!I2aTU!hxk%19Cx{GKGch>46~ zU=qWCt>%dFYB*CQ@$^Ol^kvDzTL} z^O49B{A|^SUjIV)Qg$S{JNgy-%GAK$9Z^{G_THHioxSz9r_ek>&XbK~A ztkp-1tL_ldaj2*}R!&WNv_>p`F~d~G(1ueQa?o31Bqn~-!k0m!@r`B$JhA*edLQ4w2}V_+#quze|s{v_S|0{ ze0IpTofsLnk=3EGZYhW(pa}RF6aib%RN7n$L!-88V&2K>cc=T2+emlec^s5Gtvdg8;ajBCS#CY*& zH|^;#dj=|ymr0!RtKP9AH@!ABU|p@{w`m^db!`D*-_8a)@p@#xCk{u$Hm8^yWzZZ) z(#Ro{3gX$gHdu!qKN$gEWyt@}-kUWk%WVyUf2HERHS!=hS9Ddh15T*mh9Us1u3_@R@@w!i}KxyLqAN?gr4h= zpc66l@cLAW3Hmpa8C9Gt?ocsN++V|j0M_>;L4Iv!(N!s}*K_9Lbn==ZA0QSvPN|{JUl><9Y_z=iGch__9p8X-He6D1{d5DU;S_wytEJ3iUc#rFG$T{ z8U0YFLcYn7#(^A-$EW42MzPJ8rKWvz-z^Pk;lKDIcc^$N_t#jX7jQeS&F*CGHRxT3 z>&9Kjkq`S;x4LcX6@F1xqSA>!5u7o)Xj)sUDfQ8qnD36(ug?5q#uF)mP4hMCYbA8AV|T zsEv9KLYmEXzy1_>eRL@X)rKMuzYra{l(S?bF;{2g2Z~CjrWw9kkXBRhu%qc4*iuCM zSyhCgzDkm~F|CJcmFfx7p{5)0!u6fTWzTPB2}PnGW^=`J+wo~d=$JH%Vr(T8DwRsX z!-~>3z+Z^u3#^E_x{J=r>CZMznVL=4f>9rK&m$Fus4`@OpXd#_VLX9}YDxFhjhA3L z{sww7RDXsDCL5kc7jHC)hz7@T^IcZ%UvS_c3fI3N0QulJ`bHwU^QZ?(PoREAe70W` z0##IkC%^&i$xA>w3jY^CdS#}KbX_8amM~Y<<O!yXb_1JoEtk47{b4DX2E2G=yF95J+YalW8q^yX8b2G_M(5M{IZ9VcNu?-z-B*2s zoMPej9*_VqbBy-lQj%YW?3*$>9O-@>3T=W|I*P7^9$7Pvi{Inb!PFbOqZ--uRXq=8s?;J_Ee$Vyi!EFtQ9zL5M!_$pkFFh`(XA% znb>31AWh(M6|)O;ThCuX$$3!Rh{ZSj4l=@WKa`<;q3%G&Ane|~o&byR^wb)l--26M zyuSpspaK%|y!yX6;F$I)lR*=GG=4~jT!&lX1U{(EJtc1Y zfR-O+v#oG)#*K(kXCoA?!*_Z~r?R1pJ1yLY z1%ZK*o5}8qC(wyWds{#Vq!wj&>vOxFRKNUl8|d>N`KDoj&8JgsTr-(lM~JE|z>IWF z{k8y9_mT=b01=)XN43%|`}b>@<8&W$feg&_#5H-mZyZeTwJjZ178x569bu$W2VX5{ zBPPIsag&!IZ=OTxACyx(<8AgL3kL|sRn>s=mZA*R(jBc|&3c;28WEoIm`nuF^Ln1~ z3%@M5p6m@^P1&~~kzm(y0_p9#kWiY}0^cO65i~BW^5bBvyOr(CsWVgntwFl;=Ag!3 z>(WkJ?A*3WlvZbh?+^p4-*yCAGKG!B&RYGcN$ly0MlB{Dw{@#9)~2wz<7JXAbNyEE z6DK=$mrrQ#?}{5;&X|WE)cH+7-%hU~^YL?d6!{4$CluX-yMjTnJlusH-5{eFvL9mw zU*Hg8JrpiSa>_Obfw~{iVFM=bEt_k98`$LPOh^6omK;r2r{!c#EwsjdHB$Pa)jana zW1SXseoZM>X(qIx;ei>fRBgUKbGceZSlb(WAL>|MO2-P}^oNv*Y8O@m^d`s=#xsr*^yFZLTvUN>n-*2>bU96xpu_X*JRb2UfGEs z)*RhBccGm~kI{B&Pv^^oW_Gs&cW!8hu|kAhtzICb=^c?Edd`y^lFlLIp@bSV9lq_* zo#^3vSp|?~bo>pZ6d%=~&p|G{)nAbIgNNy%)aOJJWldVFh8{Qh%{~F(6#9LOa-Y5N z!C!UbkI&>7@L<|(~AAW^&QX%TC1Z%$~ z9&7A=d7zdpZx(XxmNp^#8@g>od$wD(RK5%&6bajNMA5ubVr#G3OQk+Jw&R#uh_*isTrbHN2N`f7|s3+zj5} zE=3rh{Ax2!g&l7As?)C4PovA_IJqp*K>Ph^PX7EE~5Pu-KM- zpMIv}gCzd=?0*m?53sj~zu%*n>YQH{cA{UPyH&t8H>0vJfpLXgQ*Zds4Xu6MzO~eQ zhjj|#OKCWxFpXi5=&A7w;5LBrGojh>QRQpfpiLdysxhe64}wC^#PilTw_Im2>+YS# zq^z7yTvh9yRwJF5vkk7tlpD-=?~zJLzw(@arN=#a32C8ab~pE-8TpTj1GNCd`VtkE zeew*Tm8q?e_3{U9L_Gcne>j1Padp1~7ET2`UtO>2;z6fs{3+PDdbirCTE~VbZTD@j z(rZPvZoD^zN+p7J8C1zLdxk*vngemx2)y7Nb(iO+Vsb}z*QIxt{aLoh18P(NU1)^M zS8~ktTGf*+H^HLs5rTN~wSwqV=>{6h`UlAd01+PH59C?_gr6zS*-u%ky*#y8XEAn3 zTcS-$zLtBnx=2ntGk@H0ePgkk56JSicR59|88FgmJM-#Cv1Ce4v(g&IMyz$NTHjUz zk#6tB6GCBLhG+W2yl1lP!E#|HOQ51PC$E8aklpgFa{*RXW#BJQ-4=Q2t@}3FBE%in zsxSH;OfAf++IJ=N6vUHGpS(>Z(f=S@5~%lO<2zuP_=AKY zzv}d%CdC_Qs@62wfoTdt)q-aKT7!mzkRL2-5f&}o$^$`breU?GCEwcoyxZh_Y`O3z z13eg*F(C}KN@Z?=#uCCZeDE<`}}^zEWKSRXlvTFwk7#( zd3Rcam3{3{b8R^R>ETY+gOWB?=pJ+Ap_y@kQ(5^G?nOjR}45aaSAJ9$0i5PQDuSpngE0cjftIxT**y2{LsXgp8 z2M)|RUE0&}((N}V?8pzBCxwW)&^0bWbx<$8oD<>)``*ey?3AHJY~ufv4wiyV7LV@% zT!DD(2VpR0X0~$;hWkZ*&8-(8zBes$1a9gDLiL#^c_$2D#x{}y=&TD>lwqltgqai9 z96g->^_a``ZqJbr`P-f+fbZ*0-hvoJQI>C4jzXNm&aE&_YT0Wn^ow4mNqWw?#^l;C zJ=JrT^HFPb;iTd4KyJ5NHG=%4@u(4cml@UWod@z<8V(wfd|3?5vMj|%8SIVqYl3wk zI-g`9I!^h^emf{^j^Ki(`*DxaN;OTowhyb(w#hb@!@WnzO~PEzd)lcUS)z4pc3YBq z5$dHd+BG4D?(Ql&xfs!rM>T{_5IZwTXxY3{_e5r6GgA97+3yM%3;(C=h^BZIW0AlO z8nDtpPn=4AaEL_b@~H57b(f&AEINuz{iPR&NYcEZ4H{DK-5**)9noW$vA}nt;RLU*-en)|Kot zKDNso*ybGxe6`>KX9^y+JAL!Uoxo6^Gm4OuSnkvVw_=R$!J7~36}qI(>h^}FIc45q z*H_~*wriXV9i%Kj<`?~Cb5x$U&l`g2)uRoem-&-!40rszOYWxuM=R&Ovg!Wfa1*i@ zzT8_A>VG2=O+_PmWZ)=deOl-wo5f5X4~Oc845_B@zWN*K6z1=y~Bq6yT5wl?BnGuMfO>dpFG4>yh8%DtcG1;un6wRNIfsmgS$FPY7>G=*D zka2$n7BI>T&uaCz$Uu}F)XWJhJHzt!*keom=p;_I&0f#gk5bU9?6e)CmR5|s;NVt{_h6_`sQ5c~!^b&)lOFj;=)Gmv7pG_Rz~IV1(;6%+=LG8gLB z{zit``uSB9=D9W{QeeD~r7BOi%WfUMl+jPfKg(0{eX)f+l~2?P_?F%sg1qrG|SwhJ`mj&{Yxc(_I2`U-sca*GpLUQW!WqNgxleLu@D9#iesY=sWYKY{vZo z<6G79wtC?q3-MA}gGzTe(p*c9aG1Do*fv`(H2#5-)Q!9KCwsS0+)yO7uYR#o6-75- zt!ehg42R>}ByaToSA(lo8* z$ffz*-%OdYa2@y86Y;7JwCi$Ho?GgSihC8w)o?~{!Yc6i?|j{}Z9#i$|JGyWmH_hJ z-_1-CdWS4v^}jSKdJHH+2up5(&TtBKCmQh%D-FXcSvkpVfeCu8F*#pqYsQqA$$UOk z&WlUjs04AfKcnh8?^k*PF|1V215T|v&|SF~Z!f&PDUgL7A`H{*)jY<5bb zb(HK~m91#IDs+3^sssK?Z3i#M~N&?vX2kiTxe85l9iKMsUyG_q~ zR>g6K+BIT)p%>V!|6!|<;4iP$cwK7webHn34)k#MCwfJ?xa>*um$3Z=G=yu9BGLT`U*J|ALR~&WT%<7j>X=`v}d3K^Jn<~U^f_4F60>j}>sDK5E)9U}q<=KPn zh{MoOv5*bcVyhAo`CZ&47A|I)2rjA)YDRQRQMnbYWu3ufY7{E9M0dr%&qW5IJuQA7 zxB|U{9=Hd{dvGIh#1EBG=YT#9u7saHO|C>m1?YCDd?stl{$pc7cvJ3)IRLl9jU*i% zMjzc!fDhTS&jO=aA7f7M>i{6xZv-KfQ``rVzytjhE33owsPoqHfo#OOlLAP2!_*N_)y7KJ;!X)Z385H@9de{VF}=AfVaecX=h*lR1Ty*=nx4Yjwino0WC?WbA4B>OrW zoVk;Ec7<7@d8YnftPJ=Etqs-YU?{~%=3L%5&A=O#;?tO9>&wQ$k;M6-$(^<8Y&Mh{ z%yKldX`azJy1HOk&x&-zDa}kuuCvN%TDjy1@}9%WJ|sy5!gW-dawoV!sSAN?WER zILXsOHa=BUcs$B(GdIAR?p}?X`55TrId1h9SEky8&K@VrgBCt)bKg8H1W_8!A+y^F z8B5j=)YL0AOY23CgJhOyyel*7urU$ba^pzVc0_5sSspx}kWYGx8+o;1ohUhvxLvB` zq0KUcIu-S^@7~G?@LwP#fqTP4@(z{{@N(qxvV8KZToGrmT8HY^z5<3Ek3gH$6bZnw+M88?(VsKN_z0dukvh)5!_>rNTqO z$PP&T30+k0dOJ@-azAS|VmMj*?!W)H|AIS5{+IvbzdW*f(U;zDLndGD(;gt-I{#or z1yTYWHXwP4?U6#*7p`$|C~@NaxbC)=3%ji^+pTW5D=43eIA1KPtd7Y?2r$+P8mZq~ zQg7&{m=%?^7GAdb(_Xype$luA_rf}`v%!zxhKX~LYvk&{AxsLtDs5Ms~)eikz?dyed^@zjsj zFDF{?%Pvta(~)@{jeDWLxMyvqy5@Tgo9d3p>R>AOFJ4%U ziE?SSsqKl~RJu_8`jU#{c4L3II9lt#FAD_c-ZVJPuO2DOAI}g!CQIbW%Y!Mbs3XOV zbZ#jxk2A!Fi2UqI-#b=h+OZ~L0gL#YL6+UY-zb1QLSQTNA7E0<3kVGTIc`CIt;JSL zSo^!10cmj?$qrJ%-gyba2-%fzqt@ z`oOeEr~Qd(Gd9<49hncXrp#~mi{!!jAX3`=UfQaofe0OjN08Xu96I4{*b4!+OTOXw%5vZqmD zla7tQfN~j936qb$XHz;p&=mYQ<7XDuWLd~J%%bkmw{#U;3zyFiU0 z>=(mmxailzJ+bfl11gc!=!c0Wda~m+Re~c6Xz*e~>hq`bE|hqDmEdqtgO`_7THN;hp`qX7BKdN%)z8ZK z@0h@lGk8dfGvILHCoE9rq->RY?XXK-E}rae&X=<}wOQi$T*e7&wk)W(f(PBIpouirp@$nH~m?ib(NYX}KRqQpA_K|1M=xW!--)Z#Z- z8~uP;r0t`A3~f>7(eWbbqi(ztYNcMAA8`{V;Moc}Z;|6AV^!8dRAOo}HD7R7r+mDs zGL$i$$hq87hmeJ$bCsDgKF&5r71{&7b_mHAtG`=(zE53YIgu8@qt&PHaG!)9m2tSQ zw2d<}tV2sN!L4<+`g+AwW~MYqdRae${V@3z4UdcU>lIG}e76Q9cGKW>@ik;Y<7H$& zz{32;m3TAH7f7Ocox0anT;5)4JB^_us%mZ*XjZG_5{F0hhiF*9TdCLPx zFoRW2M)N<{)D%~98Tf#n%saph#QSsNw#R$ENVp3s zdsH~v5A=^B73k(+g%qcn1T3bQB0vLNr|RlVgbC+!90PG;0Np4k&~ zOfv)5?N7T(#F~A7<*q}5-^&aBsErO)uFAwhRe`~Sr^|M9uDVsh=7MOt7z@yw>(#BX zpv?QjvXT1!gE~YI(TdUEBGDtfSb@$UKA0^}Zz?;ryI~ruV`smf zt%lX0Z<2YFG^!K+pvWqA^%T-Kgiio^?b|@x_CS%JC9mlr_Z4kOlMy zhI@cT`|x-JA_$=6M9|xP=!X~9;b%nL9j-Q8b{a>^h^i|k)2&6kHR|>1S9d*bO!#J` zm3EzObFNrMq%OFU?9cqL6YDO$<}XB5nTArwXjgT2W)+AlKYA>Hb&)kM0KduEC-SzR zHb+rm=qlj*HvSDeQvXKUEe$5Y@AL7q$F`&<415R7swa;##XMXNU}iTk&E5EdThub+ zS98~aP;hYoz76_b%1Q7&$cn-j^4X^eEq$Z95*#FS@~pJ}_xUfv2>O>ef$%E9DP$ci#VM*ASxd3}VFvN7DBl@d!epo|A%)FH80&TFehCGz-gyHjH%LcWgV zX$@Zxe6vumY(To2{`U^6fp;wW|soJ~FPFBaX% zn#sv@J;>DO<{Rk&Lu7D(=2G0HKjNEYI}(EWR{B4yxlb(l{B*@x@@cJaq!)&r+pG`L zOM!WZ{a!_*ks`+?0`@;6y>3hUQFebDmA-Owi!wXD(vKCrZMc`<O@Awzb+`N32R$L*@$YlY^a zUG9^|apkb+FShbf*qDkca<%fj=F@~R`Ja#MtaAU3xU-gQad`kVoU+dy#g99_ao<0Z zGNtN4jX%x@n+9Z+xxLH8p3&Ue_kvbwx!u-aF59GXraPso+8R28Q%`KzorXC)594ZA zIxbsK077Z(uwv_zrqkp@UD)8hGl}5*ft24f<6BvNTLUcog^pj{KK$KhHYsq_lK$k= zp8fx~i$J3C@ZU$sGWAjK8Ztpl))_{MHMKSWV1XdmK*mq{7{^}=gr9ARF{jF$35;#E z)1FkNg|IRxQdQV}Q=T=pLq%ARX|=R-S}kou3-UB#I5{Lo$C=tFwRfEEJIzkF$Id&$ z`Ob8XHe>CwA_7+Q?kF{-7L=@lyx;dYgmkEn=khpCn$|ZJ#vO)4Q#ya-mp0f7_=HNa zAjrj!pKe-Q=H~AKsLy`@TYx|pF~L@*85#4{K8*Bvo9qx$7+uKu&^br*!VcsEmtP8u z?Y{MP`tSb@#WWtqD_VQT;r@m;A@@MP4f09wmgR1g#Ge|~zoXDQmIBcfp!R#F9ld46Z z#<5DQ+~(S08vC|mOVGw-*j#uM_jF<;mA1>4Ce1hfkw06WI;BA)-1u#46YLK3YE^SA zV_zD*9?@hYu%U(`0zSW*djJ!!s=yh*)HnvwEWTXHplmkDfqNxd(W0Za zmOG_WZgrHnL|lanTdH(VoLS$yr88O%`!Z>6_Eyu^hgW(rCrouOF0Tiy*EnzP?y_VXCy83Q7lum#`&ugv+gL% zNo3K?WyDnm-F>sQx57x?>0E0%?YGGSX4x$nEge+x9HGi=$Q|XVPW>19Cf!i@eZo^% z?B}gg3se0R~P2cj-kF&KWpP4dMBH=q^V|h4%byfFy)%CU9YP3epzQu z&E;TwEK73C)s!otl{w3(tIqgnT*;kuq^ueY>|~z-FC?KY}y^G{Zn;(@&wD=L*^#~eOxZ?Q6D$FLz_Gvn+04${H*HP z13C_L=-QB)Y_CCRv@CS&?*vc@{OEv#e4~WX@ZX0^j=ry+QIRb`&eoP^F`hq-ElfFi z*a_0pyMf(-ESet$8nvCbyL;M#zF$jgBavM}RG8j2az%qXbT*tr9N789UqwTOw#1F* zH+Hmi9E%HQJlV`taa5J3bo;RBs+}p*uTS|!uZtVoy+g$dmfx{b9`CJpQwDwe}T*OaCQRjlbAp_Zm5kIV2g4E9ci--$9qIq1|LWPVn?;xGM{9P{7*g#Ofz z`W5;!z!S`8KEg=PpWD7jGo)h2r9OY%xff?lZwH>X87)g&TC14-rLo%*q~3xSAR<4P zJ0&8tJ(W7HgJq}P@#ORI?6l8)MPK*nLwid~hA@~%qn!;&a!3+9Q{<;nePG69jGbR# z;Bs5_1v+d4gr9kDsP2{(uA@xbrC_%_m5;I4JzJHY+Me`kZ5X!UwYOzsr!d>4$MMp< zz7z(Ib*OYYwlF!@CZWFbZL_`G(|#AmPt)Cwth)s)#MEg#;t^dP1!t4T29-zYgd^%;fi{Al=IsBm_CZ-Qr8yCV!Hn`EP$B+w?hq zvuWvrB-{6RvZ8WA3nrUBU0WLM`l_o3ygJ_Y8Al%sSg&)KPHffRvy|Aqbl0_@;fx92 zYpdST?(6%A7<8qjbW&-xJsvyua!&b7mpC;0asjLGn~hY|5Vc>spGMzGY;p}AG*6Vx zTN%<#xMZUV|F~dq;=Kc3JCi^fBEHy^q zmYdlAa?v#G)xuuz<89X&jD!89S+hG8ULj7S*>u~k*Dk)(cgr%@wfdtqe|0HGG&ZxP zRkF_wqRKbJ(3c z{vL|$180M(ly60bx8s`M#ai;Up~>E54W7T6m}$`|=F{{o>=tr|vb*(GvCOWsjW+HH zUM#DdjjlI|;i=wZ_C0D)n)&mgwInvg@ennjjk$1AHZd(v=Q9|DX=$bM#$R_X+Zo}G zO{;eBSxw-h`C8BmaA`g(2jl-{<9v{IP*)r7zdjyBptYuZTwKy6U@`WRH~0wh2fr6e zvRQE{QG#o&HXNt4H=~|#J@sX856gd2tAXa3u*7#8527UNJ{Ep*1QI4#|_dK9^fwpRbomQg>F<^KsPdw42dm573qbo&nR}%f;N!a!>U% zjOC_D(%>2Z4r5gf9Z|mZ;{(u0F2ASk!2gsNkB)0oiBz06pkp&44G3vr2tN}>g+Hid zS)0i#k~#TRuGf!gUEMCb)9yGR8ho^DcV&Mn_%p90HO=0HB+Btv)@n1I;{7nDMQX%0 z*^O_G&pfIX1NQ5l> z0%8lOKjM!<)6iST^TJ^_d-*i!U6w}cc-00=y1#LyOGug{c4->qad#Ca*JESl286p_ z^N|~_x%tHM16?@=Og-!jo2`!AGAFg`u#HE0=dJM&jFBIk^rlqzi$y1JZ!1sUVYyc% zh`ZXBrs|-!Zndhicr^`$Xfd<4=mkSZmyGGe*>7FNGPiM~4ky=Qd9BZ`{!v%1E~(nn z*lfhLxhA&^rP^^?tByoMd(PKl0^Ay_l{@4c3exwO27W*Sbj%%f zWmb-e&1!ZTN2J;%N8GH_+=p@|4-Gctje!CY=jW6=6b*jLEWaiGL14;DQqPf7k_eE* z4Epx0?D;MU+hDsU7r@Nl8>Cmk0Or$50F_Ul05Sn~j-l|~pF^4dE7Fn^Tt4$$(qA+| zSJq6sbsT+QzaW~DrdD@SL;XvE)lm8Vw~~hZ>TBng-%%)jPYLvXUXl059otzzq27y$ z5vrmUY8N=9!6f&AUqJi)MWH+a$Lq-751AnFzaQ2!lc4F9v?7-K@lmPN=JvHacQ0eV zX~J-or+onL!~T+dH%8qN_n*QN$cz4q0C<9qSM>B5KBW9X5TMYEv#o2kX$=G7;8Xq6 zS?F2evAG|&$wALLGxP4X$r7V!RSXwLkoYXSusgHEKH_T!n1?x75yyG!RPJ6!kxy-F zoEg@g@L0g8${xc12f{;YDPRuHxpUaSxgqNV-Q(4(&>7()>10i}q7nk!EVPdZZi-{{ z4hRO|eNQk5yOA~RQv2qJIuR0d;{q#iGUo}hvePwBHHZdhFZJm>kOW0JpH{)xYeox| zI#c~R{ZlL5Wonv3V0G($iLm*?^y_NSqb+5?n<~h7K2>UmRa-^#Eomfh? z{Jo0E`X|5S6AU=rNc9YMI5OM~zZt!XRxq}|EY&%L zpO_swu+g zqM(nL)TjRQ!$zY=$Ay<48TN0w6mk<*R1GTO&z6Dxal*N7WpHyZaE zr-NC5Wg*-7hho&kFannQEvhq-xc6N3cVs7^ALvd#C}Ol=4NojJC+g|-{!o%O`$+fQ z67L#%{~DEo=9HTbJMwj-a{IN{8&6_)vMOsKX;p=|)0On5H*QBNO)HK$yl|HlN7&cJ zJ}#i)pBg^>$8BcRC;bg%1$I(8(eE7^D}PId#Ie#8_ydvYM-XmAg8N(h524Z@9`(LP zs@AbPZ}Hq@)J3xoi31TEwK1tq&5Nt|>Z&_$d;E|q_d|RTBX4hD?>lmPgHPIi*bDOONUQVFDG*~ycjc8X3FKHm z&$p+Un`zrc_6H%F*Y>|#I6!@@8(tSVmmx&ZJX` zlucBL_MUH$f?*rsOJWFqbky1jrObYKezfU-@;^WiC7>URNIt+CzkugqPFfAolB*5P zy^Q9|4Oy>+tFYw{YKl{hNoD4AGR*GugU zprK3Ds(S}*(l5YFk|?Pb3ZM8QoTepD{os+*Z~#4U`!2+H4`A%!Genq{W8b9|N-2b< znQ*uw;^Qe8F-m1qw4QA*K-#T&^gAB9@!#Kg2%tW80bUm~xlUz{*z9z>9&ZJkbeiR* zGd^5ts^bF(y?Jz$7oEk{yG7*vxZm+Z4*p{~xlgeX_M@B5^{2b}$sEPD)$9c`S`%Vd z8eR_G;bk0Dc!5LD+aTc&90L3SM^S%>%%+g>TGF>DsDw_pepEJFrgVy0CLe3N>5jZK z>`TxoU0q!ZXrmfCYM*Z}Ye!d~#83_{A|FP>upHbF1G2UZ>h{Km$> znwYI|Y|)lb73w14+tQGlY8z{H+1UD6A-Vmkd+dv&4n3F(v%qJGsIpWCD@E(9w8^2m zE6pUPt-le{bPinonLt-YcpP?`F2b%d~`4|Aat=9!xqL61ao$S}`I$MJF$&;RR zu}k)JcL=xL!D2r;U*@hltdE$D3_Z9mY>!q6+8WPdzub4VdF4E)cI!i?E}0cZ;J9r( z+>Fi2rZy{(>kGqJEtH&q&ai=Tvsy}a#ruV zpTu5-kt!|!xNpHq<<*- zVO|#ggA$7V1)|c{gWIvjZCc+auEf4+f}eM6iE7o-Co60*rf?CRrtd&)AUgQbwrb61 zW{rt^{Zc2ombeQmnf4M!dDqMU-1N}k8|^hk`P7V&_mi=_^;&h!?D6YLY3nF#u$D^g zd26oiulw$bVoTi_zpAZ}ILk5ScPIWec+B7DbGnRs z+a-+!Q=eXZi+=QzRj>#QD~yLHd>yJ&4F{r{tPl9^CdN4yEeK@5TG68qez@ zJTwQoZMF&66GlH_1lfPtohXix>Ja%d_GzFJjt zrCNAD-p1$g71f5gX(n`p4D_tL#$WnPpc(%FVdD{B`{&=eI4Sxe4dQBv;IrtR*mWAYlQ} zl@L_c0Ri?0f`6D1g_n$Bq7~y8h~E+4WX0gy++LzTzh1eq-Sv$2u(gd$$`fHGeg9ah zP3z)@-Ipk4A;ntfGFtYw1bs5j0aNO3g zqD5U(GIvO6IR82DaG`9F0W=;yHfwHMB5Ed0Qv2y?qBxWkvdb3R**Vos0Heo-y-Vz_ zyU;01TecZihpDFO_1p*oir#Y5D@<$YyL34q`3YUBmWmVy!Nicq%n)dX@nnoaqMdSU z@%jbM2BKA*r;w-l_YuE@h!I!3A2W;U4Isw#!2b*XfJc=l;C~)62pM*{^m6!dg7_P~ zesFuBf4&J5<@chG4sOsRpxNMwj87i=e{@_X9=P*#aeYQgP!nQaVHgsJzD&3BG-9n&Nx*mmgyQ^H8lU`MK?UHw_ggZL! zY7wi<_G06FzBD^~$v%viBOit&c8L;IAgFt=?%f%{k;$wasMXdT-A<i0U-Sp#@ky+&Cc&YnZ5+maK1D)MPlwOBNR>=@b5%jVuYm_7|?wJRiMwX*66;E`#oz3Ytr9sCOY=I3F)nk2H=GL8aGSi|r4n zd7zc5{dIlN+Neiw=L~pad1_AP1Gy?dp=Qk&mIaJG#DY(ykN<&CohyBOB-i~1I<9#{ z_Ve`}p>}f2Pl>)r>Ha|`Vvrb{2sS>~E#N8$@v7+=_6*vVbaqGoB%LUVtM-LJqk2{4 zys#aEYD^z$|+5KL77f#p#y_s1}j%`B;WV2Nt;aGiM%;=Dc z0wcAG^{X--|r7x5lD7wp@d8b`?=k z!WC;MqocbxaWvD3W?Ok69ItHs%I~&KX3x-`GZ1RV{%{!2E40C!PR(9b8ZZ3vr6ddE zzAZ>2dpjs_H046z-}de%GepXfS^Zui!!)1|NJ76#O@d$G2z8c$yIWW${1EVlv>|Ff zBOCLuO;2mkcWN|Zx7?y#TS5bn=ly)nHGa3X=&94NSK+75fkw}t`v9*bf8zV1DZr3e zGSaYlHumN&a7VPz?TOCOC#qceIROfwLs;Z?t_ww)y80;r0qMFwaMla>+lrpIKnqx_IzFJ`}3wzH?ix4)w5RpbIGXT%N>ZxLGg7$6D;(LYQ>I!6K>U;fT ztQCpa^ajO6Yzi3TD1D2?>konmY150y4hhaAHni5^`IV)OO2_TF*WX&I(HqEf-J4pM zvm&+}FnBHTJlU;h^7`06yQWu;WWk9-b!<7c{%qb`_-CUc$kOKZWE6Q!knQ4{`e!=H zjtDA_ffO*tK>8MFq)@7hV@-nf^9qj*`d zckTU@K20SVdf=XnX}>g}Wl!7^N6A$$a$MKh<~ZI&RH=Zi=mobS7>JOm+=;w*axSRN z2 z%y{d6?DMfM20Wj4Bv0k2f) z#v!OMwaKupa^i?Yyr{Mz?4zix%|u%A}WpTv$r43;Fl(M5$G`E`>h4d=v)dWm6NJoO6>xa3b= zj*vfx^nZbWA!<{YF=9NlHM-aVyiQ- z%XP>FzcdS2UNFT-7r)RJ;p5M|`;3oqZ0Mf|m+^Tc#D_t@ehT8jw-h{#`Gd|w@+=K5 z{|2Wwuy?fH-e5VFZ}tBsW}-R%aAj!bU>GRedcU)dDojj7E+|Z2&&x5iMm!kt!_%Ym z)j!0sA7JlKf4c{0F@W|nS+u*?PG}RHw(ay_%z#)AdgHzCt|*V?L&9Ypvr0fG+d*wm zsq7|=MtxQh>O@^)cH>UpQ%X{~)~|HK*0E+cLz=?H8o9Nf4i+j1{n(=o^$+|* z9Qy$lmi~ARD@VY7Ub;YS0*TuM<^Cwp#@Fy72Q0PRb7q5J+I?cxppMt5b*j&Z8l#8v&*G^vKrPrJdS5X+vU|IRbj8RPWR6RVhgA$4%&v^_yG}oksKI|&P-zA zHwWxl_=&!F&TM(PD|WLBrM5i41JWO_QH%hVkwf~&%$9l>wOO{*tF!bhf=LE7s@l_9 zhP-E1LT?T==tuP`b@?WBHfr0lxAbN297YRfI2n{L9ihJLHMnKZAB#q*+}2r{*(l@| ziK07_GH8NjrP((bzI(>UbD~6Xbfn+`AL$!xLF9ubAMx?OD$@sQYVd#qS#(@@3G=2O zh0o|LJor*&Tl`jJA#d>aA@*O~7cqA6r^No`4*`38s?qaj&Xyl4Rd=YbcFvjD4I1E- ztu|ii(3Mv!#&1Hz*sx+xTd*`=DGhbIH1eWu=`4@wz6zc7_37@iQ_EEMa$=o@Ejcgl zO7h@1Ng+k;|74_oyjup9AHP!+fs^Xo)yP`3+C%-bQ{~9((HWksL3yHV55|%$S899O zQ$nvUoVVI^RU_y1=rFBWf-)d#+sf2fmP|ruZR6^)-xXRTb5ZsS7!wIfi%~3ckh1g% zOq~FD5V~mTP=@kE>d6lip_|ubcY1t6A}$pv!ZGknStGNM%uOEqhkJhB;^(JBp8b=! zelczkr)a&^FcLdvWnn{0i=|awLt|IFTj5T8D`qy1=dOFgusrUW%aI#hrFS!&2?w3L3H&2E6 za}MKvmybJZ*5$amxa^6+;mXcpz0NojG8D&iNR}d3-Lo=w zMw4x=#g7JTyr?xso3qoHsYZE!C1;oV{w44W%Yrg;yww?1_l&OJM=CRLZ)i#Gf|s9H za&M_99PhXGd8+b)BVW6lps{V!(P-1qRnKcrl#A-|Q*&s>vcB+kzBnMx@v0P1<5{!h z`DCeSbQk+(xepZRm!{raRo#9SEBqgvHSiU_@WTT-aKdAT^*|V)&L0W3Zh4uh^8lB@ zxw@V3+!NJrgLzW)!B-#!;R(Wr=rKG6DqsCX!YRA>N-hD0XT~lqx1fRxD;N^0ianA{kz#YBnpz z&rPck@ROR&;Cqi{ka&NQyII)xC1mb~V zmq4C{xAIOHm2W42KDrE@Kc>qgkyUzl+7^U);g zLXc`<6dz3SjH?h;4KotfmK~EW+`%OlcL0^QI!<2Dv!mlbZnElb0w0_2kh! zpgxyZkzdWhhNmHb)KuJ4YcRf)I@{5FrokC=hF~AR|A>CPDm_SI(*N89-JL#@pQk0J z=#%Wb^mPWq`Tfe`Fl)&p;h*2dUlT1lMM!A_tCM`}s*y9&Ev@1xdLLS!z`zlx-f7mMw5fX1ftZ26w zq1E?o-9K6_a!bt*hJPu;QMynPR*J9eGSJY4?i>?m>*Rt5dEDD>$)7*doeV6UD5!DUTK93;J;Gt|1W%49& zVJzymP5AyObsu2wn}2U?S5W>c+o8$WakH;+$5T@bRx;_GI(xOUQZ=^gQl*8>vT9Td zPP6Vv=*X)&Dx%T(13Bw#AWl^E*=A<|`9fTy%r`dM({bn<1>(m)x8Jj&3$JkTyWIAp z({erQ>(WYTU14UIWN!T4BI?&xcEt1Z_()f+gD|eyr8C)+RGBy9(uAolW){_5liKja zGTg>0fbtAm-kTaheI<~|gV!+=-BK;S9^(yjhSU>9e^jSn#%JIb#%h3lOz1_0fB!Qk z<(OV>wia7~U2X}y)#r&-yCnx&m)62lW5kRJuNJst;xO=xMkGajzbz2zNO$M;UQAUO zW2XrRedIQWY(P45D)I^U)p&qZw-06mmeeT%3ojHPBFce3NUI=L%?h8lR5M&^?ZCN| zu1jjQ+l!E_+zJJwI-C!zj(Xif^UTwfSk^dZGI4k2QrqbRv*p&hSLhK+PBz0`WGK;& zS{kIt6EmpCpLK{~fgHDNXa5@~{=(_Y{5WC0XG#9d-Nhw&0vs@zyu^X5yyf*lk_*>3 zIFvYXeq48MMRM|K(5MN z1&!JL?VAN&z}9ZM_ne50*r#phOS5Mh^}cU%GhPU)go7J8ao@v3T!Nyk_-4|)_%(}XbJC^*HilPs(%iwY^II@t;P?{M~q z#O1f^sqNLf$P2S`esS5P%jbUI1}LHYeXnqb3)9@e{3jeFU*VQPx}aFzFNF&Pft#`+ z3XAosHaq%SeX>qQyUKn_Z_l4Bb!*}WzLAc^hfA*# zmS|fNy{L~TF~7k3t)|Dhbn@(%emq(zVazMIQF8pp+?IwL2%;{-AK0~?)yPka6S4GJ zgh;We9Fwf;j+(R4utO8k7?b3Uz8)_21Vrj?LxS0K+edt+fI}0}Y!TR436`TplcRTW zqsic5v!;hsXw3wFDV;d!Q;s7rdn2$1>e zF(8H*^h@?ch_U|2sR|aBOzW^`joJraO1#CoWlD^M?}EeG=rzQ)G36T4o^_KW=d4Ye zuGQ>@KBd}65*s>-8L?hnSDV9tiWsw6@07TANDGy#UI=w%v#7C80a4d_=fxuJ0Pl0Q zzQUqE$>IA5`rlYy5Wy7c5Jk^_dlvzbvc4OSd*opPHGKC_1KK4QJa5|7>HK-cpP=AQ zCdXc_8MN9Ts(ERS$!MY;XaA+Eytr+@Tsiv8qUvrmoYU(-(`Aa>o!7k4zyk) z0p8zO_2K9WG}95If6y!enXfq?PUvP!^~BaPB*Zo4vaL$n>KVu0)NeMwJ)wVFv=#VT zOAA+KuFH4bss00thjwewg70%HHrszW#1+%+Un^a-Y&w^X=Yf1aXK} z=aMiBw8_TVTh7W7D`c|kf@C`W2Kyiz#P(qbDQI@Ckg6$>$D#30srRdNE*YiE?a@ z%xc%K*DFyI-$IIoo=Y8;1E@P7K@Jw(AK7AmQ}I}n98vCgJ2$5B1jEXbEq@WZ|{b}cz$fIMr{S%-*T&fYMjN9;Kv3{HoEnuwA7j1Ii%|syHfEvxL6ltx?ex% z(}liS%c==c$PiDFvKu;)6xhgsDlr-q4*Sq=e3sWkfFE5A(pW@iSH1oo1^B&Q{ZPN} zE!y>8XbUkAL_otIz!)fey=x+jXAO#*xgl<;k<#srd3;7H1G*c<$z>5XFry!@ckG_) zMmv+Ahi6Vag-}P`PI_~yVy!nGWOw&kC!O_o;Y>bC72J}1wgkpmA~aO>0xB108*mC2 z68!JrdbQ49sanOAUs_szB9EZ_^krI5q=dZOaFvz=B|MF7O%NsU#vZhL`Z-vf`{HWP z(!B#0(v`rrrt7-W#nm9Zh%}D(SK_=iI~k%vZ`=#Jt(f>FIG<|7NMP#~{*wpGHT&Tk zE`qBn<`=O=SEAYQ(`=U+q3^kA61QUC>JTl?pRhZ{6$E)*8#NYC>0oaU`^~UjJFK~( z*L84@JLn#-DF=hv)G@B_4ly2*_1K$nUmo?u8rAOFJv!9PVTsenzo5&Ai5z8rwj&I( zydY*mk*1FjLs*$luR#SVbPwrx+apx{f&Bv|$}983SdO3u?A9v(a%%NX1*lCbIG~8z53fYSbKUE<|8;WK_ zV(mkNV@5iv)C;}vp5~get7=mBTx4R@=ZJ{)Vi-D|NNzSHSR*pVKM{Xi_IBBrjH1eA{%g8^?SN0{$6}naX)}|HN#}4JV zPEs4rOlEh26y}?lJYuzD(jNDxYu#K!R)Sa+*U@P`n@=mQN-J_eS&V(ONDnH^i#^YU zq<*sjZm)LorG|y=61z&8F5Wz3wOEi1;-T)t(pEgzh8)@HIzn-)57vf*=kuDnNJou zElGQkb^(3`#R~K6ga!`vMGw|BQyOX%nKg1kDJ{$mC*I^-T>YurF;nbCwtK;~K7{P0 zEq)S$$l)z?A)wE?CBJ=Y?)p7C3>UV^oweWJ!yPgOGS^914p0s9iUGQJE`a0t+1{Jg zSjhbh?X@To_I1}mWSRWfzZcn1lTD8-!_~4{ki_4g5CL^1TX?9#L;i3DbCxcUkF>_v zl|$;q*@--LmpVFu&j@Vk#jd5#KGeN+-ON963)o^)*SKrR=-jXiMI>&AwAE#QhdeURSQ7M|qgPGP@5Ej?8;y1iQzXSuGN<+99@b}gA+ zx!y*K1P&NB_D^1W&jUh|AwM1E2XvgURV0|yvsSfDlgQEsL4^~ zIGq-JfpWvyYH2gpC9h08kLOu}lpoK7JPhdZA-xkXT1j7y2pyaUJ0Bb-)D=15H_3)% z&W=gZ(zv6k(Qdl=Zx2gberaq>pCoAlzEo0XD)v=DLl19v@$g>`(<`ly=iK4%_#cV9ysRt_@5`0| z>6hQ9Ca_YgVvnif!6ybWk#cM0PYXW0xgp<0?7K121)cN?d8z2uj5G`? z`v+3eKkJ<-wP!DG#5x<9uG+jNf6e7+Cf+RG4Gj`F==M z2W;gCu~r@4JzznTQ$4=3I7@W2C&%ny7UOQy#pu-La%X}3v==1$I~B*g5%^Gc+jm}}(UDp=4VY@5Quf%z;rYrZqxZOyfAg}w^g*VaT z*COY(MZW{~x^q8PYb3sTH^;2tq0hzvLVT;OH9nLqYTYxIi|SxSx6NQ5glw-+M(7(LK`%R6 zDW5*uM$#WXwxb*`=Me&o(h4ot8WGQGeM$sH*npzFM@3JdN<>QOvpfe%kh3~f$+K5p z(z;1)NNf#f5;%@r`}M3HrE`~Z&!;U0ogJP947`p4wiIX{^8DtHtWSeQLd7+5)%`y2 z`#>u;E!Di*^41<`X>1%ke z-xfV;i^qc-&Uv@OBAb+jH%AxH&3$^I9KQ6tP{l^CdRkx&TG;exrfclHiR{FEVX))* z{fbmtlSQN?D{&?4s&;L<*V-eS!`2-}+ZfDxL%{{tjENiZXikNfsnm4@RmdxbFp?KC z`j2!EOv^>z482cA#;ZdYI%)y;-&pxIs*vl+(oq4PFDq#wgdg!-KSlVdjU3ufPg3Md z_&&LsZO-~yBC@R!H?uMNL=PlhZ)?jL2@c^0Vj*?Zp5Ee*`vwH%VA^<~4px1VFyds+ zZX>HIHO8Y6Xk!y9W-8vYHRIbQkk`|k3t?7V7-@m|Ll&5)Z>3HD`42ec{_Q^twu_=& z7ya~0ZhzQiUvYfVy7ANbxYEwe!}S}`(9!bDOO=0yK#4P|8{uPB8k zkBgOe*iVdLC^}?BYPN>Ajx~c@CL1>JS+db~IGt@ZE5@|K1#-`pqhq@o+y4Si~ zq}cQ%qt}tf$6zim@WHgzbLY(saoV=TnmKp9u4u&-^1M#iWB<(Av#KX9CuhFVq)oY7 zLOf(vQW@3J%wiM&_~$>6;UE9of2Q{T{JHCorxdII{KqH5hU$q7cxkGD^A>?FSrxYX8S^mes8tilCp%KrxxiNCyugD#P-lX(5qge52|OIJ_iG5Zq7#3$r+f{ zWTN!Yd=-%~@#jklUp}DbhxG6u(JrA0<*TDKt2v(bNzwH<{(^Ds`YeH+Inw+&#>lEb#BW!XJ=hH=X9nE*n zZYERbST`E&s@pIt1liKg1lpHgF%pW!Lz!XUfPhMgJ=B9Af^eh#z~S}{s7MIjZ`ag> zI#1%T<}_XIQm-wQp~DbV#hCjo%x%XfNf`>&hAObN?E=RkgMGq|XAn9fw}>IT2*w9_ zw!%&pK4{bXPP5lFLc4eRoH_N%4B0)vtL0QH+?V|j1t9wX06u^b1tp^XcI=_KkQPCL zEyqJ{E%;nbal%7YSW!COZ*x?QJafm{bQrX2`mDP0Itt-0H`}eE(G0)a1dY1vP3R`6 zY|V*e3Dzo(D*B~_dXg!Ce@Df(l-sRK{w5rh6I4$D=?|Zd$zMA+z83Z9ApC~=klcN2 zH|22$iYesih@H~-9_@ZI+-}wZF=>GGj)j0=~!SVJvvXqD2Mr zM^Ie}-x0ey7^M`y29EfsYK=ZQ+twX!M0qv4#$Wm@h3QVM|6FAfx%9+gs_wq(KiaW= zA!x2dQQxosrhC*k%L~%V6Xu{Z*a@qE6Z-?aJ=}3J>9gbW5nNP@auRCsDqiw|?y?Oi zlnJ$lug;RMhC%&~V_&zCjp|kFaF>M~qrR0P#Id_O35}s>)yH+c-Cwmj9akmgXzp9h zF-h)b6hjLWm8C1-2oo~{Wwfq_D|+u=OmD3^SYY;A4Q8XyD5&a$;U*W)7bSE^RKOU4 zh9VJCL6PC|nz?U-hq|d-xDq@-HCYti^hPH9FA;ufBoFb^qp}!Jmb`9U274QlVJuto z#mu7y;7Q)$*+$KuclT1fKdpLXb)?jBb6t@=g&HQl0vYZb9doKc{1@#|Br8m)px&;m zYZ^D1C?#BTeueST+P{mE`(FZ!DCf~cpUXlh^g%RC$!^G=EOkOQgCUO%@w$kQM7vgB zG};Cp%OIOaomp`4AkfFJUCi3pk;m?$Y5T2;!VWH#`fNWxYm8-C%&6s-$rAoAMOL&u z2Htx2=m&H(d)SCzultt?-Yl5yWhU^nYRN-R!E=0}$f%{FQK8` z?hW43&AjH2!4!;{-}C|YqQkcYVP1iEj9ZlR+lJviO?JL%F^az)Weg5LUjCh%yuZ!M z7xt>$D!J{e&(4mm6`APq%+TG$Bu<{0{o|>LI9w%9h;{UKJfgLTy&x zG}%F-V{0>^n*Elw&}-WYrmmI^lcJ)ivhN#-PINU#4Oo{uFe0fQsEOJSE5k`|zu}`% zy9OwouR?y*LV6xKF?)3k=dorb&}94xm(fO)TMv#W|`Zz z4!o>AFVow!<&9`Xek-k&zHKJA!F(1KWp|r}PY3&pQ@b<07^}YGj zI6}=Vyx(Y7;wT;;=LUb_ea5fKxI{&SW%Cnr-5McanBc;k@Q#i=Ud!zA)|>3#ks35!+i~ z%Mgr9lj}C#)KA{7KaGQh*>fw0!2t5Ms0zJ3w(Y1o`fTXBGC@Ir|M@sP$mh^_d|4Kg zQ#2f#1{ZPO@x(ZI=qut;S<-fl+Y@eU`@5rqAD5Lab6CcvsCJ}XR1d~F$83ANeAJh0 zRkNH#5oSYuJyxciKVT;ivHfkh+;4d5#a8#{jx&X(+burk zLgl<}jRKzpcL(AWGoCrv3)Oge#%ofz(T9z2->KI{!%u-R89W;`Tg8XZiYWUEIY>|yk2ujuiM}FL=9_K zx{Y=mE&{en_pC#+w%BcJm7wW>@Hr7&e?F+%Iva0-@O+r*BYhK4Rb_KnH|AlL&}>Pp z_fE|*WF`Jf)=@#J`|}Zgkk29e__8dbzQr3@RgLD}z`{;*-=`V}BA|!kjXl{p25m%Q zi`$tPw~_t!b`{6YXfH5Mf9ss->L_A+1A8S09bwWvbuMmoypSy;C}G(8jb!?y{{H!> z7MsW+TYOL!UB1#c$4tdqcF+D$!p2sO@kvX`8FXEK)lA!?9Cm z^p-c+VXgM%aGDM4XTk4;laWka$Rjrv%M>mC4VxAYRewH~5Ar!UA77S66svUTddpe$ z8e6fpZMQwYwcoL)lWAZVyS8E@d~O+=n4eb3al?!>ei85OP}PL$`m#JhvB?&{8MLFd zvk2&*&sT-b#r%sz>ErnMm%xdRwnZ$_H)VmOMpk4+gpQqY%hahogmP8f?PNFH4VDyE z6K1k1kWH!;OMJ7<_#AWMPeUK1?Yi6J7JckE7f;8P-KEv)LLbbzF3(qwf02PNJ)-{w z7{+<{;6=qyyLSmqSs!}tP+iUp!uMymKO+vj+U$$? zxp(LfYXXRNC5|HR)-w7yPkw^+-gE~ycHh|N81**q$ic`SY6ER3$NH z;dH=2)Pyf#5YF1_*j*FDYI}@6H+YsY4Wgsdm*sM`@)q_oTy`$=aN6QdjyXwo-ZHXh z;*`L9YoRU|%!_Yy$TW{YnnB_3nXNg6?wv;#T-}0oJVMtXuaHBL(Z67~8&w3{?SF6% zK_cc$R)d@8dCZJDB)6iM6?3RI!iZd4sNtO4e4qU)lV>>>{ZAqdy>TCJ7FYTJ=B}H+ ztV+QIlNLUY|i}>jq|~6>C=)1?MDC+0QdNiB3IVqYIGQ2l!!C2osd2#9gX5e+2N@l$V+jARJi4CbSLvu-2 zKQ$-0+*H@TzBqWLPu!!UfEa(*L}Z3@8m4$H*SHA@`>+m>nJ6f;|l~_{^kvS zS&}dE4FFpCk10gOL_le~pLwIRIq7Taq6+fJrDNRe8@d&ZoutJ;&eg|g(q6rT=)oW# z^6LaGS>tb+D)TKWvdon8Me38Hiv1ee%*g zN0#MAB+-48zBK#i1qXi8iiwW{&oTC;-U@6nneH~-QxoT=$I0m6-(tz{w^2|r=be`b zT0)Pz!txykifMo0Z`$4B4dJKmqVQO3Z`ARA(?0A3V?AF)D2(Uc$J9xPkVOJ^@kFo6ayPDLIChnWvPrLIqK`8Ao;Ov^Oi99yjGPKZvQOIA^42w_KWZZ+#@YCj?!x-(*mJ252}lJ*0l= z8AuHq5yW$sD)VE@{VrRZcTY9J@CK``TnnWA-al~BWY2bnyCtWdmCHqhRH}qHV>S)V zsWC*iH<>#VsMiYaZR)X-DV6M6EmpE~z2?oJ4+W~G&bI|;ErX9S5=w;^1 zSCAo?A6rCO$Uc(?uKoOFS$FLw-4^^q!bYbA5`GKhc~)bO>lQz}V1acBF2m7mGSG!# zzq3?YF&1@YHi0aAdg2gTEXWfu_)-+rRq0ckUd%Sf(7>ql>MzCSChVYpstG|EZBR&_A$ zbGuEmPgI6ta}h6XiJwpsB~{cqDUTw*qXu^6GM|sJPo|wm)`(ZrU-WV)J?JbG1sZeq zAJ_$ejlMo_AVELxpC=V`!+WeJk8$WfZwQM zPJ68!#!=7i4&*H!4;awm>xb2jkaU<6#BHRnrCw;jdiw{RO%I4 zus?J18KT=E;P1`EB0=_Zb>&JEjW?s7imVbU3ty3T4YsrH)VvW?t33_KV7-$^6`NNE zBk)>n$69sJg$m&VpKI8iW8%lm^bCQHj?YwD-ta_sS5@B%+N|oe5B$N0|Ep*hC~$Hb z`Tb_VX##|wM<}Hv)A2$sr7Vj=iEyN`d1)-i^2SX9tU6PIJ{#=ePNdNuT1?&RC!sB< zo5N+KC}+5uTdkROtKxgfpfa6Qg~2777}K`29O!tHiz9nPpC`>gDq)j)pE&^>;c^Ls zUZg7fDq})gQ~kSa3EyN&0AZOP-9Em~l5l_RISJ2;(2sAkBRn5}vvTl{{TmdmZ?hu& zQ6eM4ANiC6z<cSp4Pp>6xUI zfv05hp_lsC6MnZb=atnfqIV=q+9&dq@5}g>3?iMR@3-N0ZP&uqL)Ma$*%V@<+-^fv z6Nc|--f}qxtNdc6$g@EdHU+-13R@jfcQoE@OUc=QOkVA3G@Z1-fp6yOYGR#TyC1Fi c5)KW;1P~~MtH8Q1S9B3x`1D`@@n8S(Kea+F4gdfE literal 0 HcmV?d00001 diff --git a/src/FilterLists.Web.V2/package.json b/src/FilterLists.Web.V2/package.json new file mode 100644 index 000000000..1164fc68a --- /dev/null +++ b/src/FilterLists.Web.V2/package.json @@ -0,0 +1,36 @@ +{ + "name": "filterlists.web.v2", + "version": "0.1.0", + "private": true, + "dependencies": { + "@types/jest": "24.0.16", + "@types/node": "12.6.9", + "@types/react": "16.8.24", + "@types/react-dom": "16.8.5", + "react": "^16.8.6", + "react-dom": "^16.8.6", + "react-scripts": "3.0.1", + "typescript": "3.5.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/public/favicon.ico b/src/FilterLists.Web.V2/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/src/FilterLists.Web.V2/public/index.html b/src/FilterLists.Web.V2/public/index.html new file mode 100644 index 000000000..dd1ccfd4c --- /dev/null +++ b/src/FilterLists.Web.V2/public/index.html @@ -0,0 +1,38 @@ + + + + + + + + + + + React App + + + +

+ + + diff --git a/src/FilterLists.Web.V2/public/manifest.json b/src/FilterLists.Web.V2/public/manifest.json new file mode 100644 index 000000000..1f2f141fa --- /dev/null +++ b/src/FilterLists.Web.V2/public/manifest.json @@ -0,0 +1,15 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/src/FilterLists.Web.V2/src/App.css b/src/FilterLists.Web.V2/src/App.css new file mode 100644 index 000000000..b41d297ca --- /dev/null +++ b/src/FilterLists.Web.V2/src/App.css @@ -0,0 +1,33 @@ +.App { + text-align: center; +} + +.App-logo { + animation: App-logo-spin infinite 20s linear; + height: 40vmin; + pointer-events: none; +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/FilterLists.Web.V2/src/App.test.tsx b/src/FilterLists.Web.V2/src/App.test.tsx new file mode 100644 index 000000000..a754b201b --- /dev/null +++ b/src/FilterLists.Web.V2/src/App.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); +}); diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx new file mode 100644 index 000000000..226ee6316 --- /dev/null +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import logo from './logo.svg'; +import './App.css'; + +const App: React.FC = () => { + return ( + + ); +} + +export default App; diff --git a/src/FilterLists.Web.V2/src/index.css b/src/FilterLists.Web.V2/src/index.css new file mode 100644 index 000000000..ec2585e8c --- /dev/null +++ b/src/FilterLists.Web.V2/src/index.css @@ -0,0 +1,13 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/src/FilterLists.Web.V2/src/index.tsx b/src/FilterLists.Web.V2/src/index.tsx new file mode 100644 index 000000000..87d1be551 --- /dev/null +++ b/src/FilterLists.Web.V2/src/index.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import * as serviceWorker from './serviceWorker'; + +ReactDOM.render(, document.getElementById('root')); + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: https://bit.ly/CRA-PWA +serviceWorker.unregister(); diff --git a/src/FilterLists.Web.V2/src/logo.svg b/src/FilterLists.Web.V2/src/logo.svg new file mode 100644 index 000000000..6b60c1042 --- /dev/null +++ b/src/FilterLists.Web.V2/src/logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/FilterLists.Web.V2/src/react-app-env.d.ts b/src/FilterLists.Web.V2/src/react-app-env.d.ts new file mode 100644 index 000000000..6431bc5fc --- /dev/null +++ b/src/FilterLists.Web.V2/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/FilterLists.Web.V2/src/serviceWorker.ts b/src/FilterLists.Web.V2/src/serviceWorker.ts new file mode 100644 index 000000000..15d90cb81 --- /dev/null +++ b/src/FilterLists.Web.V2/src/serviceWorker.ts @@ -0,0 +1,143 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read https://bit.ly/CRA-PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.1/8 is considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +type Config = { + onSuccess?: (registration: ServiceWorkerRegistration) => void; + onUpdate?: (registration: ServiceWorkerRegistration) => void; +}; + +export function register(config?: Config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL( + (process as { env: { [key: string]: string } }).env.PUBLIC_URL, + window.location.href + ); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://bit.ly/CRA-PWA' + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl: string, config?: Config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + ); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl: string, config?: Config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); + if ( + response.status === 404 || + (contentType != null && contentType.indexOf('javascript') === -1) + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then(registration => { + registration.unregister(); + }); + } +} diff --git a/src/FilterLists.Web.V2/tsconfig.json b/src/FilterLists.Web.V2/tsconfig.json new file mode 100644 index 000000000..0980b23fa --- /dev/null +++ b/src/FilterLists.Web.V2/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve" + }, + "include": [ + "src" + ] +} From 305b374a3e5c566d571f042e238e9ca9d9eab066 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 16:23:16 -0500 Subject: [PATCH 002/163] add proxy to prod API --- src/FilterLists.Web.V2/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FilterLists.Web.V2/package.json b/src/FilterLists.Web.V2/package.json index 1164fc68a..8abe5e477 100644 --- a/src/FilterLists.Web.V2/package.json +++ b/src/FilterLists.Web.V2/package.json @@ -18,6 +18,7 @@ "test": "react-scripts test", "eject": "react-scripts eject" }, + "proxy": "https://filterlists.com", "eslintConfig": { "extends": "react-app" }, From 6d175e8da0cc3b19943ff26d0e6d1d153646d3bf Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 16:24:41 -0500 Subject: [PATCH 003/163] ren app --- src/FilterLists.Web.V2/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/package.json b/src/FilterLists.Web.V2/package.json index 8abe5e477..575525925 100644 --- a/src/FilterLists.Web.V2/package.json +++ b/src/FilterLists.Web.V2/package.json @@ -1,5 +1,5 @@ { - "name": "filterlists.web.v2", + "name": "filterlists.web", "version": "0.1.0", "private": true, "dependencies": { From 0341478d134706cbcbe4b832fee20468bd42997b Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 16:25:36 -0500 Subject: [PATCH 004/163] install antd --- src/FilterLists.Web.V2/package-lock.json | Bin 503543 -> 540822 bytes src/FilterLists.Web.V2/package.json | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index fe5c5e8b7947e44643fcc9713e0e33571dca23a0..a4a4fdeb04b0d6ceb0c8cbf4e583bb7ca785a293 100644 GIT binary patch delta 21078 zcmch9dypf?d0*kVszjFPjo3+*Eb$~evLlzmOB}BiSrTc>NlBJ0o=TRTSdqv|BE?op(v@S2jA%JM z1MDtdSu3lTJRaEDO(M$m^yx)3k>*Dd_G*$ODk*vq9ro&?ji;NkZaO0fU zMJX+*San3(RTb~brC3xM37E6kQ`_y#c+z$f9WB!zx`e>U;cry>K01R0__!-2RVs}Z z=*jl=BfL1)$E2WZ@4UG76tandmlLK_7ZygPaE!)n!2elogOx;$8-XJ+%PRP0+JyPu zqNS$KX8#AY4cC_I#Va(S4js-Rt~i)bt?tOgaa3wcg%CCgYEJjKksH^$wNiK@N)4^8 z5Cf+qXVhV&opLx+v`Z;4`A|*h_a>Qc6(7|(HYyjG0=m^ZaM{xA*TL;SFr7F!WE7DX zo5uVw@M7J(dT4&kJPU4o+O!H@c*u^QTC9*neJyx6WpMoicDNKjIsR-r5Os9WVp|X; ztWpy2rpN6Oqj{GvI}C)nls`d6@M16QP+A?Okj*C>O_@f!4AUIes@Y_liS}tvyp9CJ zIW!TMbNv|Jj}XJFSJw_)g#Z4@6ULvledCx?f9;)H$Na~iZ=0eLEyY(zi;b-3;3#l~2KZuq^t#x|YWGaU-HOH2zxxV%3 zpV+tGVKcRyM>gtGcY_;na6=2cs&OKC?tAug;PB%%)XCKA`>Htw4)@L#;OWm;*1?Z{ zXthy+(Foy3QOXs`(Y{vAm54dJt!6&g5@`qRjtqtsygDehD?LI{`Bp3dE@#X057Q~J8+uq4_L6x5x9<;PHukyGaWf#(!iy( z{glPMi2~DSESN5#>iS6GpAEf`9M~VB*$m=rx{*lH!%(#(?T7|Dv8>CTuNGsjV2x$!0prSdNgH$CnA_kO0A!~tdu@KjYv9B$($wZ@AqNJf85BmKAxOB|4eqo+f z?jRh%d;hcb#IyStTi?RZpqt1hvNqi(`j)x-UNIWGmKtkgnN#OE$dC&<7j0tmUuBd- z3Nzl&6pq_y@PfvD_(khUotKYX!#79sEm?t4Rgvj(>TG=ICcaQF$?!YU1}pG#O=6Tf z5Wi$OSyI&vM&!GU#!I3x24vH->6(90=QUQ4R8G})2D#XP6MKDL;Wpbw&rj);!M851 zJigYIx{yVUm(WcVTYO9E^4cc2@QUda_{u@c!_Rs*(fM8#reVAY>9I&Ug`EwUn|+wr zbT7QfZm^8NiFHQN8$9FNL_C|GeJxa$sdLj7aBaMs&n}Q1cEYwewo{Wv#z%}fEq_B2 z1V&bkVLStw0ogZ>I?o7_A@QH_LaHv#kKL#%%y2dYbo1FI4uK=6E0SE7hQ_i$e%nt6 zuFh+cvY``sZ}s3vmg&)ul}r`{vp%N0<=S-bTNBuz zZ;;9h-$s{5AW9nF;MrX+d&a%|iD%)2Wv0oCdu@OeQ6NZ| zt=axcl@mDD;7G_9=sZI{dvOiE4CVd~R}h;xT+^jBhq6|lc6}$lRENCAwv5h^P2c?2 zjgM7w znNbE=?tY_bh?qJ0pl}BJdQkXgb2R4nq1`K3v28s(^zb=++7)@^+Sud8;T0l*a z92rIAdNLJiA``;tuelk5tp{p--j}PzNh%+XMx!N9hr%7{Y|K3=6mxXB$#RC5{mdYTlP;l!TmbEjZPRv6ED-}7-5Bu>5=S=l|ouP+CXt!T1>4}aB)zGJV$*=q}fn3Zj~z^!kZ*UyFOfqbeE z^WYdU9%thW&Z=b6iKnxH+|@Pk?e~~ZY`^%V`A?4>TGado=mPJ%3i~|pE|cEpV!aN* z_LXh8w{nkPp}0&nl%EU&-BE#vmL~mX8>2@8k%^BOFNJoH2=6L;ddy%ru18~yej(aJ z>r~L?OJMW;gh=s(Iz|R45p$r%z!4(dp=D1Mz?t+x9CIwAA@Gkswi_V$VPMl% zjvrkd-JCW1o)4Hk;A>U0{n6QUjJmtquaF-vnN90-q9Zd&GM{Rxl-iVCbu>*n^FA!> z0N}WFUvgQ z1m_Q19;KZa;c)ty5EIQ;@J>31W@6b%qTwU)CQ)ivEA1Aa4yOCDVomLOv~nO4Bh_fI z?Z?V}B!CUdag8ojB^1x#L?+h>%4t87mB5iz+dBA*kC+~MY;74TFYoG^PC&tpbMqL$%b?Hw=O)vYX$QoQg5PhEjHAP4M**X zs}>T`KtGI6nuSQ0lN3rJ`=xQE(_*xUoXLmQ+eU)kQE6y0ls_$#>B>U=Z6G@SP8vJ*#^FeKxWgT!+q$+~aHKkPX}?dZPKkI4L26 zyt{?=372E6i_{bWZoSvCb{KvEng9^;8VKactAI(`pq%=B^OGiP6{Em&AvBtrc?#*=!82SB7_(gUTupKX33NG)V?L2X2;ar*vU_ z2t4I9J!)96OHGEeE|-fp5OC|NY3%}>W;QLRG*_%UjQM*p1Pj-PPCipB)uI@b`Cr^N zD-T$qU7-Qfr=X|h#m~cq{ae|Do`OKUp>4Evfxq(;8uW;33+hBV8N%CzK+z|5vaLq3 zj5eEWK1pKXgo;l}Js->UGfsl=%jJ4HQ1Eu!d8(i3bN+dULJ zsVxI+X-}{RBi)Nc)+X3d5)xbJd@T2dU&|`ZhpV8H{%?Cef zdF)(P;>dB0$I`i0DvJhNRc#O)_Oh|AAL^v-k9^JideT1gS=?GTot~<`7jBylfT#Y4 z`LXl5Ph(nbpeVz~vGWYo-lhLyT|eV3^m~1b=Hob_OfWuAtE^ffWGbmNx8HZx@}*5v z4cz>5`)Qjlgb{G#=gjCsI<4VQ^*@jz1i1Jf^Ch@3M(I)o*BH8!j|{m)}0nT zL7xj;U$s90o`1yl@I$;RbtOe^@$5!}(^zo9X+8-)`?&om`0{nkJupE*z|%MylMSRwUD5PbTyBT+jz(8(#p<6CDS2dqjm-KIMYe+d;eg27+n3B z>97Ste{ku5odEa$)ON&py8ftTee2p~D=kVwu3U9uNk=W~q$5J7!NmIQvd^CwMTXs+ zFGFG7jOG~+#sr^0TJB+w3dI9_dlDhjR3ISu#8SJ0A?^N{6w!n`hqRJO3cSp&IKXFq zYCC9hgX{NOp4g5iEN{Nc)Sn^^`GyIq6cDo$J+mHneAEozA3wpf8=!FIo?EKt-NbZ+xy5R6bY24x`&V-k% zr?Pc97B5jGpKw;PA;`49@T-=O9yDF>zc7DuCiLA%A+RF1cH@dtQ2O49XQ%*wlEwI8+5PI9a30(!VMEtu27Of zcsP)f=wgQR$4d!!$Qe*dwNXCe?s_7V3MPoLVI=R@b@!1ehTx~{hCsV>>n7B27k@iaN`a8S?GTAf|oyM!A|W69XRM+0R;VU-YMV>c`0fed39QD(0=a$?q=qo{Ypt=e005tyGF%o z$5~|>VXY8Wg&Y&|;)OxF!>Wklb=T2sF^?jX;$-9-^(zCPmgcb3h(yw9Z%N_;EShge zB+c!gAY3#!a_6oB^v9Mj-M6!E!S%t)xvk7M@yknlxuwr_aeKG6Ui{|zS!APd+?#*J_-(f+K@SDZAo zBgj9r9tF|QSzleLb2X_ivRlk|SAqOXHq7Yd?5uRIkDZbYsI;aVtf_G|=OoZ=gvhYd zSLW$rid3rO4uTW29`4)ZRYqy{yWqLAmUG~R*US$ZfhnVp3$r??9P}MEo626H5uyUF zzcL*?mqb`!i)HwnBs$4R#aqY^>nY4R$ycOVPZrn{kpI?l_QM}C9|F&aD~}p|tm>bG zHv8iDbtB#lKGcBL7RONvpGx$`1st))mBbhdxodIo%d z)A}Iz&SxyftnWKx)ChBnH*E_|F$`S)d)xZCVH?kDBeIiF*;LvYZB3YtNTo70VxSwD zI&*B-{@D7dM=Tqvwsi~Qs+a!Af}iN}A`c5BMgQ{d199?MM|| zJqOcQR7bv%)Sdd5FWp7n8VVQH-Hza;gO-cn*I&0CJ#uI7(!=xKps8&DZn7rVi93H9 z>Sx<|lLuV7X!CmS+~i(*0ENCN&ldB`SBgrH9b4At&cc zlm=?1gw~vln`w-4)z+|+t5b-Q%?9EwrBbf9u|b+;AQqZLsi>nJcJ>O|Xb6}!^V;_P ze{DT{5WMz=<%|XTSGG(jc692V*Vo7J(;I%5+{pY$rB?Jd9Jqky_$KG~L*vAWkEwJI z%c706Tqw1jF3#J|v17tZ5}a2;MY54~x-lo(8GDLD%LW-iJ!1_jR zEgR#q;UtJ^>PKi2vI@C$>LGvLdG6&$=^x7kh@f*%fPPYXax z5Ng*?tyAe%6$_||k(aG>(Lq7+lM0$0gfkqjmVylzT}kG9B(4tVO4I9bQiVp5>|?%m zC4l({IjqoCeT8bX-i!E~iqvZaTk$$I1{Yzx>gW!rpMgi+ZwIceSP{{niH<|PfTz>RY0;t-t$NboQY7Nl=txs(6|2K$l@SvP$k}0RS2wu9 z2Y=pV122Eqbb5RAgiZUt6^3kP*0lWJtkx~%ljuq4Y~Qh^cYZ9e9 z8wp2G?NF@-=FicE7!29Oob`a(U{cjaIwXy{zUVL$ z=iNH(4!{>?Av(|tn@(9^pkeE|L)f{!a@|Wk_q3t6xc$LLC~+W#${kPE6(ob2r{)bu zg#=$tv>i~^l$c>IQs~q?P?zG(axT`8dbzmAG4Z3B=Gfao@}qQZl&&(YEtoz9FBgrCycPN z;AEo&PpO2Mmr5QKbwIBmigfBpPp8yN2nmOqkCsCtX~dG_ZhI(s3T%uo^Nw@{>k`>! z&u4Ji3-7ep59|dxj9|1Ly?u+RADm5nx_`jUm6fB%U=q*1=^L?~m6`ShKmF&{vrB0+ zx38F|>@y9{ZZXfD0x$w&1+{A{sJ{JnqP8>I%wo73=<~PCFv}Q;6drbZ zdr?PA%*ml>w%RBmbk~InbTm|~%hj|5;|c*+xQ&g7$biy@YzmP{!J`G;Fyz*Ua{_XO<#|^Jom*Xj?Dd2j4Sd>)^Fj%c-qbJl3uJ-x(@p8gZWz zWBPl;YnYj|$3JMah67)Zlzg>rE*1$Vm6o&3gyxrv=;=Xp6aIWcj$Z^f?J<6 zL$~gmHthJUWM`x6wNR8~SD^y$*V-)6Xl4a(HKZztqfLo<4dZyCfrq1mAwdtSk^^sI zsdgOZfg#;=)lUjIS1M;DEJ$%=GU4#n#|44c{M~*GX-R=BChjS4@A7mOm)lSz3!W`F zRDDL^h4a?q;G?hGR^Cef&vF~U%RhmB#b3Lzg6Yh>lkhNGzghYNbkjUXn6A*Wt6ULX zLnR}VRkT4zLU<*P(?r~#W<6v9x~Rk|UhhclIumN-;v`qqioQfD#0^`cPEi;|3bk6j z%popWYx@N%RPqf%!_Z!oz<>o8=3v1c=8PM1K73a>Z^$VLa~6E~GH1 z@^km5$^s|sIM5AJK$YZLl!v>1C8OSOY{OKcRSUl9F=%TuXbb-3!IcZ(YxC<kJ}yp!|{z)#Z|&Q8cBs{!0h$z;qJ^AzMO}X|t84 z2a&_MhQp7G90|>Nv`RXNV0R=2M|`GI&6DLovXxDH38E@0TD9kK@?XHlGc*=bA>8VaNcJY*; z(9GU#Y^3bnjrLGo&5P^1nDhXV%qO;+?V037)U436rkWo=p1?|8=z znn4zXte|rd47K~ft%vO=A7o+B&PW-98DqeR;k;6w8g-Ar3GCJF=&kvZ4VYVIn0P@A zb#X*RV4Z0vE|vK#EewOj`pDgwcuSssm(DQQ#3TFrrEtWX&IbR|bFU)|e^tIM<66XpgMH;g>Ov+12*XE^#fwY)6EyL#}4tJfH| z1Fqk;UDOq}o)rgP_%uvtF?<(4^sF2JFTQGdR99v@8FSNZvhxJJ-nn01xk5J>Pd)99 zr6{HqZ;(v}5xZT+ml<~x&Z@uYgywA#L0VX+9faYJVu%`eLN!t-y1F7>am1PSpj^O3 zXE`io=|b2c4iiq2D?zFK_HtT{m4Cb9Y8kQZWcod2Wcn>9HO?%a8TZ^FMQqoMhWTTz zwXH9G^Z_Fs>|TIjM(X|+dHOU=Ax6PX((XQCkhs4~-u{L$o~@S?>jjrgr_!#f;*JEu zqqNMZgzP10iYpTXKBm!`T)ET7NOfE$(CUPqczw}kq%WZ94&wF4!jzVr^y)BuJ5AxG zV$G8!Gnp8;brgCx^d0lm-FZu&^^%$RHf79STm;f=3p8H>9qPs&pgj)g*XjC;jZ~rG&O{5zah_?aaW6Jb3)^X*4-i#Ev;-S$L; z?#s|k5hHEYpn^ru4!bRzFg=%aFPn8rg1u)wiENr&&=iZLG%Utyd0r^twQ{8t2+5SH zXkD^I$tia)!TQcp@SZqlJnBB}Af9rp!xCpy*oGc^TMTA-SO&;@1!8_qfK>WLNXC>*e!8ay4I z{%Zr>x;eT+Gv%@eYSLbvQ8Kjb+ zSh6;#c?wmmit$*8%S%-zI~+IjWJ%36BU&w?kL=i<&Y4L=Xc-vPKCz$WjNR9}4~7x- z+}L{wL$dgKJkn7brbm^DM#DXV z=P8B>7l#NQek6t(<22&Q*XkWFm5w=;ST-JO!~8)~;#+yS<0H|4GZH0arqvb(i6T;L zJAf%V!w!Z9>D&|WE=j|^^hSd?({!UHxOESSX;AOkW$MkH6j%VvkTUn&$#aTqX%6ts zMLp)3OUMTA%bTqb1?>rfdpNYN{d6&v_$hd>?Yov$yS{4hjL}WOylOKt%?+J)Y9|AI zww6XV`Ub2A(0;i>1!#_tvmzn-@ps)K3^mw22I@IB1*cBI9We+%>EfJa|+a_!}w!&L4i z2M(;?BNjxI3wU|Q+xOK!Fr8WQ_UVV@3`%J*rRE<4G7I{qWZVN8cdZ&m$cCfljEB^O8n34_G}?=}OEFg!*UAza4E9`|cwj(OT7B1Ks88j< z-iX1=e(0O?3D z9b98)GCL{9>t%%1!r6eMrDwMoa4hjQl-z=c;*K&1o(O=k5$K9Idvc-iZs?lZy8ZRH z5gU37QSjh`FZ0qXrV}eOdlBTeZMc2<0Fb9G=fO42@*sFgGCy%-)&!Dvr}6ExmZRY5 zzcZgalj_s%MzT0|cY4D-lJPlWF_z?zX30H-W3f2Er`~Tr0*E)^QH57mtjG231Q%!P zx>pao;6_Ygwsx}(1#49pZ^4aF0wrKsDOf19(s5iaMf!P!X6fdD<1nJ;&h?RYGZkWj zNGs~jvyN_WtV$Vgi}aB>q%t0MVq-VPG$ItmwaHSj5DQmbLbvJKGd|x2MAJ?AV>45J znhC8dQ+V71y!xtXey6QIyU(dUrx+F;a(h;{{xRt8&`ps!Cl@5r-38X&;PE*_%kMi` zva@9Wf7bUweSLS%3Qeu^gI_e`m*$Ii4D;P~Fd@+mTqd|x=_H>N836|Pm5wi|WRq+# zrAS$^mvkomK?-Y5e5pyUsj+A-jVJtMrWxT|(Q=jR%7q+N2{b)kk3=d#GCv60jL?9gi@mih{^*f_cN2zn(VboV5q)9YEXD}uwW~+G5AJr5p>Pt!)c;-FZ4#Ma{ zDdTlRAH3h?DK_G&FI=nEyOC@$R4WI#OxEYq?eVFM+QX-pmgfb>wQ#5k8n>S_pE9onDiKN>*Cuk-9S9AbTE75u zmh$4n!DlrG&y4bv(k$oiq-`&(-3{9s>c>b-I{*I&Zy|Y!edqD?*%}f~_v0-~xOu*V zxMtI}p|J1^t9O-y9wV}Umz=5nnr&&7ZoJFl+F@(t5Y%r!`k|RPJX^Neri2_1GsKR8 zYu7BN=^#nLRLPncu0?whU$EiJFvW<^4c%cHrN)aQJROlJJBB?qLQsL0tc~3&o-4a2 z@v5WgZ?-!{5W{^4U_f0wH=j0o`sozhrBC}9T4&1 zp7}C(@vP;5jvK7cKW4RoXa1@E9rpkbR`9XkGM_wm4-^5D{B9pLJHhX~ALhG59Pto% z`du&~^xHoRQ`}$pWzz$?2gG2dt?UoZf$aBeHVb4Vfcy)q_u@{~uEv>)Iw*Cg>;~TV ziz|=P*uamo@`$DDU9^|+6g9uEhfviCydb31_4y~^+ z&=b4;c3lqE$wVa5XpclKER){6Mh-h+U=n5v{p=Dzyu%_-Jt1=l;127&gf6BFIEOIi zx7TcSrx{N78C;@=NM1fbckK z=3@^p?joJQfO!ZeE+1Ys+fMErjWilfodCK71aMMEABG0y;>j2sTt8+$`Ow^+)7Jv% z-8?Xtlmu=bGoN?}QezIfd5ppf_e`(Ybb*^eNLt9zj$LLp!tf?sKR|0>hbiOkh$$nf z2kH;ph-Gx~fTsFdNv>K_sXv)J)W}m+yiIq%?_^SgD!HqG-;P;s#HClOODt+|hJIdchXMDgfH_WF zLS&0%#NINeODCLh`ddHpu?jAI!Hnsisp*06DcPpKp+nFx3NtNVDDKBbAtIHdt7y=b zp$n9oPR0D~Xj{yn&0uvfYOW;d!wI@nCYuxz z8dU4y#;#HLc8E5$&(AG+K4-F3Cz*a(iEg=@p{w({f8`7eJrIDow&K`53G)9V1VSpe7zk<%|(U&+!=U|6&_7}5PbHG{fP_nZ$T=|Kf=re6!d;$<;t08 zI|*TQ4^>KhqTo*^gDHQ;87)Ui8k?G?ANqB(?Lj>w-so7*%)WL5<~Hee>h||f+WW`v z+qolPdXVVpAHx^}jQwDj^(&xu>hyC(vnlS}D4@$e-DP$O9^=Ridj;2|MrSD^%@Tty zfv9DFPL1_p5cIdLYY#6RG1CX)0*8n8llSc$VgT2iFey~eufKnDCpUgtrYF9^u;|p^ z4F1hycH80Qj5Zh*fEQG4eBX+>@3IPegI~VrV0!Lg4P*m$TiH(*Y9yW%GqkS`-8@{$ z%jAerx8g69=~zi|(A}`FhH#ClpP59`8Hd7_DR^a6Jt4vzWSJVW`LR%>E5njEie#gW zB-bfUNL_Z{c+7ru`{@n)>-X6qO?U1+G8q}-vn)kec&Gc0fSxN(We1YW@5Q86zniO9 zG7VQR>yYa?x$WcW8p#a24z$OI-F=Gnl)0SjtTs3;$^?D?3m3CQ!fg?*%6YRMK&723nb=n+-2Rd z`4)Fb7>B87-2R0pj@{|532^(1FuUn}585%$-M(Zj|D7+YfJuCM=%kb!R^jQ5dNd;; zsF>?lg=na&^~*3pT*^SP*ys!I1ww-Vl<2k9RZ>og@+p~dyj|E|#K1^M*8rO84 znHQOR!<*heqF>3SpOUGJU0ozD(ba;GCEMkqmd%#DE~Z*)#FEZ>A?qc>oxCXW$$*k@ z5~*N9YPzX$f%13RPSBBu+0CPKVrjHDQ`@Pd=`qdNgur)lr#8i^0R7mt{DKrf4EekVA zu{xNDeW!=r{_cObf9x?B!=Bygw{`O`PJ@GAHDjl>-7@&)y$8tZFvU;*sxPZhDOcV* zO!|Ek+lD7G(QJm{)w-j(-9NMvUb%nwng}4j0B;(QZIGfDvu5=2@(mJt4@;LyfLH&- za^+mDQyRtFL^JG^5|bzzM=-V6Px{dgU-ni!Dja%SoZ-8IMBMqSWf*-3cQN>CEtxPhMVeniUbq-+;*K;`?p* z9qhS_M_|}Mk>leuilT{9Y!Hn*!yb3JP#w6cf|Ft4A)-71Ln82&h!hocHj;t-NGlS2 znP4Y+rnp+H_GJp*=EBlcliw%CRGOz=S6t^4317RY! zH|YbxH<$Dw1h}`{BLonrx8ckLKOL9;@&pi*_YoAAfbRh|mvHd}2bWaq1bw%T?*uyq zx0dw;swKBf9t8{yw@NGp=mfV Date: Sun, 4 Aug 2019 16:28:19 -0500 Subject: [PATCH 005/163] import antd css --- src/FilterLists.Web.V2/src/App.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FilterLists.Web.V2/src/App.css b/src/FilterLists.Web.V2/src/App.css index b41d297ca..29865aeac 100644 --- a/src/FilterLists.Web.V2/src/App.css +++ b/src/FilterLists.Web.V2/src/App.css @@ -1,3 +1,5 @@ +@import "~antd/dist/antd.css"; + .App { text-align: center; } From be60e41fe83571ddcf38197c5d011dbb9853b171 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 16:38:04 -0500 Subject: [PATCH 006/163] lazy-load antd resources --- src/FilterLists.Web.V2/config-overrides.js | 9 +++++++++ src/FilterLists.Web.V2/package-lock.json | Bin 540822 -> 542414 bytes src/FilterLists.Web.V2/package.json | 9 ++++++--- src/FilterLists.Web.V2/src/App.css | 2 -- src/FilterLists.Web.V2/src/App.tsx | 17 ++--------------- 5 files changed, 17 insertions(+), 20 deletions(-) create mode 100644 src/FilterLists.Web.V2/config-overrides.js diff --git a/src/FilterLists.Web.V2/config-overrides.js b/src/FilterLists.Web.V2/config-overrides.js new file mode 100644 index 000000000..7373d107d --- /dev/null +++ b/src/FilterLists.Web.V2/config-overrides.js @@ -0,0 +1,9 @@ +const { override, fixBabelImports } = require('customize-cra'); + +module.exports = override( + fixBabelImports('import', { + libraryName: 'antd', + libraryDirectory: 'es', + style: 'css', + }), +); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index a4a4fdeb04b0d6ceb0c8cbf4e583bb7ca785a293..c6c1284cc9249255342a3c76d7c9c5956fbdb3c0 100644 GIT binary patch delta 687 zcmY*XOH9*n7*DsZ!+;ok5C{?&q9l@TYqz${cyQ~wCu1)LqX&|*m94W~OS|_8jJU*v zC^q4LFu{?S;Ee=`i-{(BGG4rRD$&?nt z0}_SRvAIx^;v;SwLxqS*RSt)wMpfVlPpy%PCm4@L(uulQEmh(xQF!}Srzoh(R|S>Ng1&EtA+Wb;z=3@SLAJILc;uhdxuf!2ri7le zqj;wbmN%yH)J&Sj87;0BnaCVf^HO#-knyb8J}s^N~311v_6&1(7PUL>vf)+=}j b)PKXagZD3cA#mv(f;5j>Nc*T|e*5AN#i8&? delta 55 zcmX@tt2nJuv0)42*VguicE;@u?M(X=+Z$Ff0WtIThE*)DUD|a%ux!`)z-qIlU1&Mm LcA@3$d*%ZGz%dw< diff --git a/src/FilterLists.Web.V2/package.json b/src/FilterLists.Web.V2/package.json index 7ce25f6f1..9554ac1bc 100644 --- a/src/FilterLists.Web.V2/package.json +++ b/src/FilterLists.Web.V2/package.json @@ -8,15 +8,18 @@ "@types/react": "16.8.24", "@types/react-dom": "16.8.5", "antd": "^3.21.0", + "babel-plugin-import": "^1.12.0", + "customize-cra": "^0.4.1", "react": "^16.8.6", + "react-app-rewired": "^2.1.3", "react-dom": "^16.8.6", "react-scripts": "3.0.1", "typescript": "3.5.3" }, "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", + "start": "react-app-rewired start", + "build": "react-app-rewired build", + "test": "react-app-rewired test", "eject": "react-scripts eject" }, "proxy": "https://filterlists.com", diff --git a/src/FilterLists.Web.V2/src/App.css b/src/FilterLists.Web.V2/src/App.css index 29865aeac..b41d297ca 100644 --- a/src/FilterLists.Web.V2/src/App.css +++ b/src/FilterLists.Web.V2/src/App.css @@ -1,5 +1,3 @@ -@import "~antd/dist/antd.css"; - .App { text-align: center; } diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 226ee6316..689b99593 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,24 +1,11 @@ import React from 'react'; -import logo from './logo.svg'; import './App.css'; +import { Button } from 'antd'; const App: React.FC = () => { return (
-
- logo -

- Edit src/App.tsx and save to reload. -

- - Learn React - -
+
); } From 2d6280a315a098c0c59d748ca3edf276d4b2c4f9 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 16:41:47 -0500 Subject: [PATCH 007/163] tidies and rm some boilerplate --- src/FilterLists.Web.V2/package-lock.json | Bin 542414 -> 542413 bytes src/FilterLists.Web.V2/package.json | 2 +- src/FilterLists.Web.V2/src/App.css | 33 -------------------- src/FilterLists.Web.V2/src/App.tsx | 2 +- src/FilterLists.Web.V2/src/index.css | 6 ++-- src/FilterLists.Web.V2/src/index.tsx | 2 +- src/FilterLists.Web.V2/src/logo.svg | 7 ----- src/FilterLists.Web.V2/src/serviceWorker.ts | 16 +++++----- src/FilterLists.Web.V2/tsconfig.json | 2 +- 9 files changed, 15 insertions(+), 55 deletions(-) delete mode 100644 src/FilterLists.Web.V2/src/logo.svg diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index c6c1284cc9249255342a3c76d7c9c5956fbdb3c0..15449eb4e06ba87ef51fee84dcafd92157f57ed1 100644 GIT binary patch delta 25 gcmX@tt9Z6ov7v>rg{g(Pg{6hHg{_5s3&&YE0Dip){{R30 delta 27 icmX@xt9Y(gv7v>rg{g(Pg{6hHg{_5s3&&YEMlJx5#0d%j diff --git a/src/FilterLists.Web.V2/package.json b/src/FilterLists.Web.V2/package.json index 9554ac1bc..8c6e4ee0b 100644 --- a/src/FilterLists.Web.V2/package.json +++ b/src/FilterLists.Web.V2/package.json @@ -38,4 +38,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/App.css b/src/FilterLists.Web.V2/src/App.css index b41d297ca..e69de29bb 100644 --- a/src/FilterLists.Web.V2/src/App.css +++ b/src/FilterLists.Web.V2/src/App.css @@ -1,33 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - animation: App-logo-spin infinite 20s linear; - height: 40vmin; - pointer-events: none; -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 689b99593..70a5b15fe 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,6 +1,6 @@ +import { Button } from 'antd'; import React from 'react'; import './App.css'; -import { Button } from 'antd'; const App: React.FC = () => { return ( diff --git a/src/FilterLists.Web.V2/src/index.css b/src/FilterLists.Web.V2/src/index.css index ec2585e8c..4a1df4db7 100644 --- a/src/FilterLists.Web.V2/src/index.css +++ b/src/FilterLists.Web.V2/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/src/FilterLists.Web.V2/src/index.tsx b/src/FilterLists.Web.V2/src/index.tsx index 87d1be551..57a536ca7 100644 --- a/src/FilterLists.Web.V2/src/index.tsx +++ b/src/FilterLists.Web.V2/src/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import './index.css'; import App from './App'; +import './index.css'; import * as serviceWorker from './serviceWorker'; ReactDOM.render(, document.getElementById('root')); diff --git a/src/FilterLists.Web.V2/src/logo.svg b/src/FilterLists.Web.V2/src/logo.svg deleted file mode 100644 index 6b60c1042..000000000 --- a/src/FilterLists.Web.V2/src/logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/FilterLists.Web.V2/src/serviceWorker.ts b/src/FilterLists.Web.V2/src/serviceWorker.ts index 15d90cb81..b3793f855 100644 --- a/src/FilterLists.Web.V2/src/serviceWorker.ts +++ b/src/FilterLists.Web.V2/src/serviceWorker.ts @@ -12,12 +12,12 @@ const isLocalhost = Boolean( window.location.hostname === 'localhost' || - // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || - // 127.0.0.1/8 is considered localhost for IPv4. - window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.1/8 is considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) ); type Config = { @@ -51,7 +51,7 @@ export function register(config?: Config) { navigator.serviceWorker.ready.then(() => { console.log( 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://bit.ly/CRA-PWA' + 'worker. To learn more, visit https://bit.ly/CRA-PWA' ); }); } else { @@ -79,7 +79,7 @@ function registerValidSW(swUrl: string, config?: Config) { // content until all client tabs are closed. console.log( 'New content is available and will be used when all ' + - 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' ); // Execute callback diff --git a/src/FilterLists.Web.V2/tsconfig.json b/src/FilterLists.Web.V2/tsconfig.json index 0980b23fa..755462aec 100644 --- a/src/FilterLists.Web.V2/tsconfig.json +++ b/src/FilterLists.Web.V2/tsconfig.json @@ -22,4 +22,4 @@ "include": [ "src" ] -} +} \ No newline at end of file From 756fe20dc03d67d9aa3344c633e53d29f7416c28 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 17:03:11 -0500 Subject: [PATCH 008/163] wire up sample table --- src/FilterLists.Web.V2/src/AllListsTable.tsx | 61 ++++++++++++++++++++ src/FilterLists.Web.V2/src/App.tsx | 4 +- 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/AllListsTable.tsx diff --git a/src/FilterLists.Web.V2/src/AllListsTable.tsx b/src/FilterLists.Web.V2/src/AllListsTable.tsx new file mode 100644 index 000000000..09231becc --- /dev/null +++ b/src/FilterLists.Web.V2/src/AllListsTable.tsx @@ -0,0 +1,61 @@ +import { Table } from 'antd'; +import * as React from "react"; + +const columns = [ + { + title: 'Name', + dataIndex: 'name', + sorter: true, + render: (name: { first: any; last: any; }) => `${name.first} ${name.last}`, + width: '20%', + }, + { + title: 'Gender', + dataIndex: 'gender', + filters: [{ text: 'Male', value: 'male' }, { text: 'Female', value: 'female' }], + width: '20%', + }, + { + title: 'Email', + dataIndex: 'email', + }, +]; + +interface State { + data: []; + loading: boolean; +} + +export class AllListsTable extends React.Component<{}, State> { + constructor(props: any) { + super(props); + this.state = { + data: [], + loading: false, + }; + } + + componentDidMount() { + this.fetch(); + } + + fetch = () => { + this.setState({ loading: true }); + fetch("https://randomuser.me/api") + .then(response => response.json()) + .then(json => { + this.setState({ data: json.results }); + this.setState({ loading: false }) + }) + }; + + render() { + return ( + + ); + } +} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 70a5b15fe..788e799fd 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,11 +1,11 @@ -import { Button } from 'antd'; import React from 'react'; +import { AllListsTable } from './AllListsTable'; import './App.css'; const App: React.FC = () => { return (
- +
); } From 44061745e9ac8608a0af2394d59c0f56674f0e3c Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 17:48:54 -0500 Subject: [PATCH 009/163] use real FilterLists data from API --- src/FilterLists.Web.V2/src/App.tsx | 6 ++--- .../allListsTable}/AllListsTable.tsx | 26 +++++-------------- .../src/modules/allListsTable/List.ts | 22 ++++++++++++++++ .../src/modules/allListsTable/index.ts | 3 +++ src/FilterLists.Web.V2/src/modules/index.ts | 3 +++ 5 files changed, 37 insertions(+), 23 deletions(-) rename src/FilterLists.Web.V2/src/{ => modules/allListsTable}/AllListsTable.tsx (58%) create mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/List.ts create mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/index.ts create mode 100644 src/FilterLists.Web.V2/src/modules/index.ts diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 788e799fd..4eba24811 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,12 +1,10 @@ import React from 'react'; -import { AllListsTable } from './AllListsTable'; +import { AllListsTable } from './modules'; import './App.css'; const App: React.FC = () => { return ( -
- -
+ ); } diff --git a/src/FilterLists.Web.V2/src/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx similarity index 58% rename from src/FilterLists.Web.V2/src/AllListsTable.tsx rename to src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 09231becc..18deea19b 100644 --- a/src/FilterLists.Web.V2/src/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,28 +1,16 @@ import { Table } from 'antd'; import * as React from "react"; +import { List } from './List'; const columns = [ { title: 'Name', dataIndex: 'name', - sorter: true, - render: (name: { first: any; last: any; }) => `${name.first} ${name.last}`, - width: '20%', - }, - { - title: 'Gender', - dataIndex: 'gender', - filters: [{ text: 'Male', value: 'male' }, { text: 'Female', value: 'female' }], - width: '20%', - }, - { - title: 'Email', - dataIndex: 'email', - }, + } ]; interface State { - data: []; + data: List[]; loading: boolean; } @@ -39,13 +27,12 @@ export class AllListsTable extends React.Component<{}, State> { this.fetch(); } - fetch = () => { + fetch() { this.setState({ loading: true }); - fetch("https://randomuser.me/api") + fetch("/api/v1/lists") .then(response => response.json()) .then(json => { - this.setState({ data: json.results }); - this.setState({ loading: false }) + this.setState({ data: json, loading: false }); }) }; @@ -53,6 +40,7 @@ export class AllListsTable extends React.Component<{}, State> { return (
record.id.toString()} dataSource={this.state.data} loading={this.state.loading} /> diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/List.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/List.ts new file mode 100644 index 000000000..cbc034223 --- /dev/null +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/List.ts @@ -0,0 +1,22 @@ +export interface List { + id: number; + chatUrl: string; + description: string; + descriptionSourceUrl: string; + donateUrl: string; + emailAddress: string; + forumUrl: string; + homeUrl: string; + issuesUrl: string; + languageIds: number[]; + licenseId: number; + maintainerIds: number[]; + name: string; + policyUrl: string; + publishedDate: string; + submissionUrl: string; + syntaxId: number; + tagIds: number[]; + viewUrl: string; + viewUrlMirrors: string[]; +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/index.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/index.ts new file mode 100644 index 000000000..fd3e7fb18 --- /dev/null +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/index.ts @@ -0,0 +1,3 @@ +import { AllListsTable } from './AllListsTable' + +export { AllListsTable } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/modules/index.ts b/src/FilterLists.Web.V2/src/modules/index.ts new file mode 100644 index 000000000..820f33938 --- /dev/null +++ b/src/FilterLists.Web.V2/src/modules/index.ts @@ -0,0 +1,3 @@ +import { AllListsTable } from './allListsTable' + +export { AllListsTable } \ No newline at end of file From d9a298878772a2c5711391ab610cdcf4990528f8 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 17:59:22 -0500 Subject: [PATCH 010/163] extract column defs to new file --- .../src/modules/allListsTable/AllListsTable.tsx | 8 +------- .../src/modules/allListsTable/columns.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 18deea19b..491c50659 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,13 +1,7 @@ import { Table } from 'antd'; import * as React from "react"; import { List } from './List'; - -const columns = [ - { - title: 'Name', - dataIndex: 'name', - } -]; +import { columns } from './columns'; interface State { data: List[]; diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts new file mode 100644 index 000000000..b53ec27dc --- /dev/null +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts @@ -0,0 +1,9 @@ +import { ColumnProps } from "antd/lib/table"; +import { List } from './List'; + +export const columns: ColumnProps[] = [ + { + title: 'Name', + dataIndex: 'name', + } +]; From 83b11c035b770a06dd106d1c8ed5453be4b8b81a Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 18:15:40 -0500 Subject: [PATCH 011/163] use small table size --- .../src/modules/allListsTable/AllListsTable.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 491c50659..14078e2ec 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -33,6 +33,7 @@ export class AllListsTable extends React.Component<{}, State> { render() { return (
record.id.toString()} dataSource={this.state.data} From cfc90adc9d30a0532f1476c046b8e33fb540f6df Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 18:16:01 -0500 Subject: [PATCH 012/163] use strongly-typed column dataIndex bindings --- .../src/modules/allListsTable/columns.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts index b53ec27dc..238615323 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts @@ -1,9 +1,23 @@ import { ColumnProps } from "antd/lib/table"; import { List } from './List'; +const nameof = (name: Extract): string => name; + export const columns: ColumnProps[] = [ { title: 'Name', - dataIndex: 'name', + dataIndex: nameof("name") + }, + { + title: 'Description', + dataIndex: nameof("description") + }, + { + title: 'Languages', + dataIndex: nameof("languageIds") + }, + { + title: 'Tags', + dataIndex: nameof("tagIds") } ]; From 025e75739d2f38c2948af7040aee0dab942aee10 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 18:56:20 -0500 Subject: [PATCH 013/163] adjust column defs --- .../modules/allListsTable/AllListsTable.tsx | 5 ++-- .../src/modules/allListsTable/columnProps.ts | 28 +++++++++++++++++++ .../src/modules/allListsTable/columns.ts | 23 --------------- 3 files changed, 31 insertions(+), 25 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/columnProps.ts delete mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 14078e2ec..850d2143b 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,7 +1,7 @@ import { Table } from 'antd'; import * as React from "react"; +import { columnProps } from './columnProps'; import { List } from './List'; -import { columns } from './columns'; interface State { data: List[]; @@ -34,7 +34,8 @@ export class AllListsTable extends React.Component<{}, State> { return (
record.id.toString()} dataSource={this.state.data} loading={this.state.loading} diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/columnProps.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/columnProps.ts new file mode 100644 index 000000000..9c5b34197 --- /dev/null +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/columnProps.ts @@ -0,0 +1,28 @@ +import { ColumnProps } from "antd/lib/table"; +import { List } from './List'; + +const nameof = (name: Extract): string => name; + +export const columnProps: ColumnProps[] = [ + { + title: 'Name', + dataIndex: nameof("name"), + width: 200, + fixed: 'left' + }, + { + title: 'Description', + dataIndex: nameof("description"), + width: 400 + }, + { + title: 'Languages', + dataIndex: nameof("languageIds"), + width: 400 + }, + { + title: 'Tags', + dataIndex: nameof("tagIds"), + width: 400 + } +]; diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts deleted file mode 100644 index 238615323..000000000 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/columns.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ColumnProps } from "antd/lib/table"; -import { List } from './List'; - -const nameof = (name: Extract): string => name; - -export const columns: ColumnProps[] = [ - { - title: 'Name', - dataIndex: nameof("name") - }, - { - title: 'Description', - dataIndex: nameof("description") - }, - { - title: 'Languages', - dataIndex: nameof("languageIds") - }, - { - title: 'Tags', - dataIndex: nameof("tagIds") - } -]; From 0767831573d1c95f507f3d49197e8a2a265b0ef5 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 19:30:53 -0500 Subject: [PATCH 014/163] use newer TS table def syntax --- .../modules/allListsTable/AllListsTable.tsx | 14 ++++------ .../src/modules/allListsTable/columnProps.ts | 28 ------------------- src/FilterLists.Web.V2/src/utils/index.ts | 3 ++ src/FilterLists.Web.V2/src/utils/nameof.ts | 2 ++ 4 files changed, 10 insertions(+), 37 deletions(-) delete mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/columnProps.ts create mode 100644 src/FilterLists.Web.V2/src/utils/index.ts create mode 100644 src/FilterLists.Web.V2/src/utils/nameof.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 850d2143b..311a4c9a5 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,6 +1,6 @@ import { Table } from 'antd'; import * as React from "react"; -import { columnProps } from './columnProps'; +import { nameof } from '../../utils'; import { List } from './List'; interface State { @@ -32,14 +32,10 @@ export class AllListsTable extends React.Component<{}, State> { render() { return ( -
record.id.toString()} - dataSource={this.state.data} - loading={this.state.loading} - /> + dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.loading}> + title="Name" dataIndex={nameof("name")} /> + title="Description" dataIndex={nameof("description")} /> +
); } } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/columnProps.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/columnProps.ts deleted file mode 100644 index 9c5b34197..000000000 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/columnProps.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ColumnProps } from "antd/lib/table"; -import { List } from './List'; - -const nameof = (name: Extract): string => name; - -export const columnProps: ColumnProps[] = [ - { - title: 'Name', - dataIndex: nameof("name"), - width: 200, - fixed: 'left' - }, - { - title: 'Description', - dataIndex: nameof("description"), - width: 400 - }, - { - title: 'Languages', - dataIndex: nameof("languageIds"), - width: 400 - }, - { - title: 'Tags', - dataIndex: nameof("tagIds"), - width: 400 - } -]; diff --git a/src/FilterLists.Web.V2/src/utils/index.ts b/src/FilterLists.Web.V2/src/utils/index.ts new file mode 100644 index 000000000..47426d11c --- /dev/null +++ b/src/FilterLists.Web.V2/src/utils/index.ts @@ -0,0 +1,3 @@ +import { nameof } from './nameof' + +export { nameof } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/utils/nameof.ts b/src/FilterLists.Web.V2/src/utils/nameof.ts new file mode 100644 index 000000000..82c8d92ce --- /dev/null +++ b/src/FilterLists.Web.V2/src/utils/nameof.ts @@ -0,0 +1,2 @@ +//https://stackoverflow.com/a/50470026/2343739 +export const nameof = (name: Extract): string => name; \ No newline at end of file From 4bf23bcc3497428299fbbc441c3c6146046cf34e Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 20:00:36 -0500 Subject: [PATCH 015/163] rm unnecessary extra function --- .../src/modules/allListsTable/AllListsTable.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 311a4c9a5..276606647 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -18,17 +18,11 @@ export class AllListsTable extends React.Component<{}, State> { } componentDidMount() { - this.fetch(); - } - - fetch() { this.setState({ loading: true }); fetch("/api/v1/lists") .then(response => response.json()) - .then(json => { - this.setState({ data: json, loading: false }); - }) - }; + .then(json => { this.setState({ data: json, loading: false }); }) + } render() { return ( From c4cca5d126fb333781adfb558b683d23b3aa323a Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 20:19:35 -0500 Subject: [PATCH 016/163] use antd layout template --- src/FilterLists.Web.V2/src/App.tsx | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 4eba24811..ba8fd2e0f 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,11 +1,30 @@ +import { Layout, Menu } from 'antd'; import React from 'react'; -import { AllListsTable } from './modules'; import './App.css'; +import { AllListsTable } from './modules'; + +const { Header, Content, Footer } = Layout; const App: React.FC = () => { return ( - + +
+
+ + +
+ +
+ +
+
+
©2019 Collin M. Barrett
+
); } -export default App; +export default App; \ No newline at end of file From 0e1a22ed7b22e118521baa1f0f35075e7cd47b0f Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 20:30:27 -0500 Subject: [PATCH 017/163] mv pagination to top to make click more consistent --- .../src/modules/allListsTable/AllListsTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 276606647..867057062 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -26,8 +26,8 @@ export class AllListsTable extends React.Component<{}, State> { render() { return ( - dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.loading}> - title="Name" dataIndex={nameof("name")} /> + pagination={{ position: "top" }} dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.loading}> + title="Name" dataIndex={nameof("name")} width={250} fixed="left" /> title="Description" dataIndex={nameof("description")} /> ); From b779a9de45488af36375ab8fc7f592f5cc900bf7 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 4 Aug 2019 20:33:27 -0500 Subject: [PATCH 018/163] use small table --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 867057062..2f36701e0 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -26,7 +26,7 @@ export class AllListsTable extends React.Component<{}, State> { render() { return ( - pagination={{ position: "top" }} dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.loading}> + dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.loading} size="small" pagination={{ position: "top", size: "small" }} > title="Name" dataIndex={nameof("name")} width={250} fixed="left" /> title="Description" dataIndex={nameof("description")} /> From dc7325b7de12bf213e51e688dc55dc912d3770d9 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 14:58:22 -0500 Subject: [PATCH 019/163] rm need for separate loading boolean in state --- src/FilterLists.Web.V2/package-lock.json | Bin 542413 -> 542414 bytes src/FilterLists.Web.V2/package.json | 2 +- .../modules/allListsTable/AllListsTable.tsx | 43 ++++++++---------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index 15449eb4e06ba87ef51fee84dcafd92157f57ed1..c6c1284cc9249255342a3c76d7c9c5956fbdb3c0 100644 GIT binary patch delta 27 icmX@xt9Y(gv7v>rg{g(Pg{6hHg{_5s3&&YEMlJx5#0d%j delta 25 gcmX@tt9Z6ov7v>rg{g(Pg{6hHg{_5s3&&YE0Dip){{R30 diff --git a/src/FilterLists.Web.V2/package.json b/src/FilterLists.Web.V2/package.json index 8c6e4ee0b..9554ac1bc 100644 --- a/src/FilterLists.Web.V2/package.json +++ b/src/FilterLists.Web.V2/package.json @@ -38,4 +38,4 @@ "last 1 safari version" ] } -} \ No newline at end of file +} diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 2f36701e0..cb14efdbe 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -4,32 +4,29 @@ import { nameof } from '../../utils'; import { List } from './List'; interface State { - data: List[]; - loading: boolean; + data: List[]; } export class AllListsTable extends React.Component<{}, State> { - constructor(props: any) { - super(props); - this.state = { - data: [], - loading: false, - }; - } + constructor(props: any) { + super(props); + this.state = { + data: [] + }; + } - componentDidMount() { - this.setState({ loading: true }); - fetch("/api/v1/lists") - .then(response => response.json()) - .then(json => { this.setState({ data: json, loading: false }); }) - } + componentDidMount() { + fetch("/api/v1/lists") + .then(response => response.json()) + .then(json => { this.setState({ data: json }); }) + } - render() { - return ( - dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.loading} size="small" pagination={{ position: "top", size: "small" }} > - title="Name" dataIndex={nameof("name")} width={250} fixed="left" /> - title="Description" dataIndex={nameof("description")} /> - - ); - } + render() { + return ( + dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.data.length > 0 ? false : true} size="small" pagination={{ position: "top", size: "small" }} > + title="Name" dataIndex={nameof("name")} width={250} fixed="left" /> + title="Description" dataIndex={nameof("description")} /> + + ); + } } \ No newline at end of file From 42b9d4e5566d6fffe173fea537bd512474232595 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 15:12:25 -0500 Subject: [PATCH 020/163] chop table def line --- .../src/modules/allListsTable/AllListsTable.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index cb14efdbe..d55d55745 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -23,7 +23,12 @@ export class AllListsTable extends React.Component<{}, State> { render() { return ( - dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.data.length > 0 ? false : true} size="small" pagination={{ position: "top", size: "small" }} > + + dataSource={this.state.data} + rowKey={record => record.id.toString()} + loading={this.state.data.length > 0 ? false : true} + size="small" + pagination={{ position: "top", size: "small" }} > title="Name" dataIndex={nameof("name")} width={250} fixed="left" /> title="Description" dataIndex={nameof("description")} /> From 108cccbcd81bd32caaecc41f1c4e2eb9dc240365 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 15:14:57 -0500 Subject: [PATCH 021/163] use middle table size --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index d55d55745..fa2f5ce7d 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -27,7 +27,7 @@ export class AllListsTable extends React.Component<{}, State> { dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.data.length > 0 ? false : true} - size="small" + size="middle" pagination={{ position: "top", size: "small" }} > title="Name" dataIndex={nameof("name")} width={250} fixed="left" /> title="Description" dataIndex={nameof("description")} /> From c5dfe682deb537240d139cd036da24bf0cb10910 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 15:43:09 -0500 Subject: [PATCH 022/163] initial add SubscribeButton column --- .../modules/allListsTable/AllListsTable.tsx | 17 +++++- .../src/shared/SubscribeButton.tsx | 56 +++++++++++++++++++ src/FilterLists.Web.V2/src/shared/index.ts | 3 + 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx create mode 100644 src/FilterLists.Web.V2/src/shared/index.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index fa2f5ce7d..482fb214d 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,5 +1,6 @@ import { Table } from 'antd'; import * as React from "react"; +import { SubscribeButton } from '../../shared/'; import { nameof } from '../../utils'; import { List } from './List'; @@ -29,8 +30,20 @@ export class AllListsTable extends React.Component<{}, State> { loading={this.state.data.length > 0 ? false : true} size="middle" pagination={{ position: "top", size: "small" }} > - title="Name" dataIndex={nameof("name")} width={250} fixed="left" /> - title="Description" dataIndex={nameof("description")} /> + + title="Name" + dataIndex={nameof("name")} + width={250} + fixed="left" /> + + title="Description" + dataIndex={nameof("description")} /> + title="Subscribe" + dataIndex={nameof("viewUrl")} + width={100} + fixed="right" + render={(text: any, record: List, index: number) => } + /> ); } diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx new file mode 100644 index 000000000..f55794893 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -0,0 +1,56 @@ +import * as React from "react"; +import { Button } from 'antd'; +import { ButtonType } from "antd/lib/button"; + +interface Props { + name: string; + url: string; + text?: string; +}; + +export const SubscribeButton = (props: Props) => { + let buttonType: ButtonType; + let titlePrefix: string; + + if (props.url.indexOf(".onion/") > 0) { + buttonType = "ghost"; + titlePrefix = "Tor address - "; + } else if (props.url.indexOf("http://") === 0) { + buttonType = "danger"; + titlePrefix = "Not Secure - "; + } else { + buttonType = "primary"; + titlePrefix = ""; + } + + const hrefTitle = `${encodeURIComponent(props.name)}`; + let href; + if (props.url.indexOf(".tpl") > 0) { + href = `javascript:window.external.msAddTrackingProtectionList('${encodeURIComponent(props.url)}', '${hrefTitle}')`; + } else if (props.url.indexOf(".lsrules") > 0) { + href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.url)}`; + } else if (props.url.indexOf("?hostformat=littlesnitch") > 0) { + href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.url)}`; + } else { + href = `abp:subscribe?location=${encodeURIComponent(props.url)}&title=${hrefTitle}`; + }; + + let title; + if (props.url.indexOf(".tpl") > 0) { + title = `${titlePrefix}Subscribe to ${props.name} with Internet Explorer's Tracking Protection List feature.`; + } else if (props.url.indexOf(".lsrules") > 0) { + title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; + } else if (props.url.indexOf("?hostformat=littlesnitch") > 0) { + title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; + } else { + title = `${titlePrefix}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; + }; + + return props.url + ? + : null; +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/index.ts b/src/FilterLists.Web.V2/src/shared/index.ts new file mode 100644 index 000000000..08f333155 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/index.ts @@ -0,0 +1,3 @@ +import { SubscribeButton } from './SubscribeButton'; + +export { SubscribeButton } \ No newline at end of file From a4d77d4b4b748a71f57ab49794ace98ab3f4089a Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 16:17:34 -0500 Subject: [PATCH 023/163] refactor SubscribeButton --- .../modules/allListsTable/AllListsTable.tsx | 2 +- .../src/shared/SubscribeButton.tsx | 68 +++++++++---------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 482fb214d..c896e435d 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -42,7 +42,7 @@ export class AllListsTable extends React.Component<{}, State> { dataIndex={nameof("viewUrl")} width={100} fixed="right" - render={(text: any, record: List, index: number) => } + render={(text: string, record: List, index: number) => } /> ); diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index f55794893..852a29c6e 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -1,56 +1,54 @@ import * as React from "react"; import { Button } from 'antd'; -import { ButtonType } from "antd/lib/button"; +import { ButtonType, ButtonProps } from "antd/lib/button"; interface Props { name: string; - url: string; + viewUrl: string; text?: string; }; -export const SubscribeButton = (props: Props) => { - let buttonType: ButtonType; +export const SubscribeButton = (props: Props) => props.viewUrl + ? + : null; + +function buildButtonProps(props: Props): ButtonProps { + let type: ButtonType; let titlePrefix: string; - if (props.url.indexOf(".onion/") > 0) { - buttonType = "ghost"; + if (props.viewUrl.indexOf(".onion/") > 0) { + type = "ghost"; titlePrefix = "Tor address - "; - } else if (props.url.indexOf("http://") === 0) { - buttonType = "danger"; + } + else if (props.viewUrl.indexOf("http://") === 0) { + type = "danger"; titlePrefix = "Not Secure - "; - } else { - buttonType = "primary"; + } + else { + type = "primary"; titlePrefix = ""; } const hrefTitle = `${encodeURIComponent(props.name)}`; - let href; - if (props.url.indexOf(".tpl") > 0) { - href = `javascript:window.external.msAddTrackingProtectionList('${encodeURIComponent(props.url)}', '${hrefTitle}')`; - } else if (props.url.indexOf(".lsrules") > 0) { - href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.url)}`; - } else if (props.url.indexOf("?hostformat=littlesnitch") > 0) { - href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.url)}`; - } else { - href = `abp:subscribe?location=${encodeURIComponent(props.url)}&title=${hrefTitle}`; - }; + let href: string; + let title: string; - let title; - if (props.url.indexOf(".tpl") > 0) { + if (props.viewUrl.indexOf(".tpl") > 0) { + href = `javascript:window.external.msAddTrackingProtectionList('${encodeURIComponent(props.viewUrl)}', '${hrefTitle}')`; title = `${titlePrefix}Subscribe to ${props.name} with Internet Explorer's Tracking Protection List feature.`; - } else if (props.url.indexOf(".lsrules") > 0) { + } + else if (props.viewUrl.indexOf(".lsrules") > 0) { + href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.viewUrl)}`; title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; - } else if (props.url.indexOf("?hostformat=littlesnitch") > 0) { + } + else if (props.viewUrl.indexOf("?hostformat=littlesnitch") > 0) { + href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.viewUrl)}`; title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; - } else { + } + else { + href = `abp:subscribe?location=${encodeURIComponent(props.viewUrl)}&title=${hrefTitle}`; title = `${titlePrefix}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; - }; - - return props.url - ? - : null; -}; \ No newline at end of file + } + + return { type, href, title } as ButtonProps +} From f31eb1b82cc069b7a6c7033c78c6a06ab1b51a76 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 17:40:37 -0500 Subject: [PATCH 024/163] tidy buildButtonProps() --- .../src/shared/SubscribeButton.tsx | 75 ++++++++++--------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index 852a29c6e..244c1f507 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -1,6 +1,6 @@ -import * as React from "react"; import { Button } from 'antd'; -import { ButtonType, ButtonProps } from "antd/lib/button"; +import { ButtonProps, ButtonType } from "antd/lib/button"; +import * as React from "react"; interface Props { name: string; @@ -13,42 +13,45 @@ export const SubscribeButton = (props: Props) => props.viewUrl : null; function buildButtonProps(props: Props): ButtonProps { - let type: ButtonType; - let titlePrefix: string; - - if (props.viewUrl.indexOf(".onion/") > 0) { - type = "ghost"; - titlePrefix = "Tor address - "; - } - else if (props.viewUrl.indexOf("http://") === 0) { - type = "danger"; - titlePrefix = "Not Secure - "; - } - else { - type = "primary"; - titlePrefix = ""; - } + let type: ButtonType = "primary"; const hrefTitle = `${encodeURIComponent(props.name)}`; - let href: string; - let title: string; + let href: string = `abp:subscribe?location=${encodeURIComponent(props.viewUrl)}&title=${hrefTitle}`; - if (props.viewUrl.indexOf(".tpl") > 0) { - href = `javascript:window.external.msAddTrackingProtectionList('${encodeURIComponent(props.viewUrl)}', '${hrefTitle}')`; - title = `${titlePrefix}Subscribe to ${props.name} with Internet Explorer's Tracking Protection List feature.`; + let titlePrefix = ""; + let title: string = ""; + + const contains = (match: string) => props.viewUrl.indexOf(match) > 0; + + switch (contains) { + + // HTTP protocols + case contains(".onion/").valueOf: + type = "ghost"; + titlePrefix = "Tor address - "; + break; + case contains("http://").valueOf: + type = "danger"; + titlePrefix = "Not Secure - "; + break; + + // Software protocols + case contains(".tpl").valueOf: + href = `javascript:window.external.msAddTrackingProtectionList('${encodeURIComponent(props.viewUrl)}', '${hrefTitle}')`; + title = `${titlePrefix}Subscribe to ${props.name} with Internet Explorer's Tracking Protection List feature.`; + break; + case contains(".lsrules").valueOf: + href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.viewUrl)}`; + title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; + break; + case contains("?hostformat=littlesnitch").valueOf: + href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.viewUrl)}`; + title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; + break; + default: + title = `${titlePrefix}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; + break; } - else if (props.viewUrl.indexOf(".lsrules") > 0) { - href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.viewUrl)}`; - title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; - } - else if (props.viewUrl.indexOf("?hostformat=littlesnitch") > 0) { - href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.viewUrl)}`; - title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; - } - else { - href = `abp:subscribe?location=${encodeURIComponent(props.viewUrl)}&title=${hrefTitle}`; - title = `${titlePrefix}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; - } - + return { type, href, title } as ButtonProps -} +} \ No newline at end of file From b5f43df6a830be93ccbb9bd05a670e7cfc7ed7a7 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 20:25:34 -0500 Subject: [PATCH 025/163] fix SubscribeButton switch statement --- .../src/shared/SubscribeButton.tsx | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index 244c1f507..47c6e8f2d 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -12,46 +12,45 @@ export const SubscribeButton = (props: Props) => props.viewUrl ? : null; -function buildButtonProps(props: Props): ButtonProps { +const buildButtonProps = (props: Props) => { let type: ButtonType = "primary"; + const hrefLocation = `${encodeURIComponent(props.viewUrl)}`; const hrefTitle = `${encodeURIComponent(props.name)}`; - let href: string = `abp:subscribe?location=${encodeURIComponent(props.viewUrl)}&title=${hrefTitle}`; + let href = `abp:subscribe?location=${hrefLocation}&title=${hrefTitle}`; - let titlePrefix = ""; - let title: string = ""; + const defaultTitle = (prefix?: string) => `${prefix || ""}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; + let title: string; - const contains = (match: string) => props.viewUrl.indexOf(match) > 0; - - switch (contains) { + switch (true) { // HTTP protocols - case contains(".onion/").valueOf: + case props.viewUrl.includes(".onion/"): type = "ghost"; - titlePrefix = "Tor address - "; + title = defaultTitle("Tor address - "); break; - case contains("http://").valueOf: + case props.viewUrl.includes("http://"): type = "danger"; - titlePrefix = "Not Secure - "; + title = defaultTitle("Not Secure - "); break; // Software protocols - case contains(".tpl").valueOf: - href = `javascript:window.external.msAddTrackingProtectionList('${encodeURIComponent(props.viewUrl)}', '${hrefTitle}')`; - title = `${titlePrefix}Subscribe to ${props.name} with Internet Explorer's Tracking Protection List feature.`; + case props.viewUrl.includes(".tpl"): + href = `javascript:window.external.msAddTrackingProtectionList('${hrefLocation}', '${hrefTitle}')`; + title = `Subscribe to ${props.name} with Internet Explorer's Tracking Protection List feature.`; break; - case contains(".lsrules").valueOf: - href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.viewUrl)}`; - title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; + case props.viewUrl.includes(".lsrules"): + href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; + title = `Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; break; - case contains("?hostformat=littlesnitch").valueOf: - href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.viewUrl)}`; - title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; + case props.viewUrl.includes("?hostformat=littlesnitch"): + href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; + title = `Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; break; default: - title = `${titlePrefix}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; + title = defaultTitle(); break; } return { type, href, title } as ButtonProps -} \ No newline at end of file +} From f6257065407e058f8a3780af3f449b1d6e7107d6 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 20:29:40 -0500 Subject: [PATCH 026/163] simplify loading check --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index c896e435d..47fcd0f0e 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -27,7 +27,7 @@ export class AllListsTable extends React.Component<{}, State> { dataSource={this.state.data} rowKey={record => record.id.toString()} - loading={this.state.data.length > 0 ? false : true} + loading={this.state.data.length == 0 ? true : false} size="middle" pagination={{ position: "top", size: "small" }} > From 26ad94bc7a565a761d60cf5f59f104d061c11b27 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 20:44:33 -0500 Subject: [PATCH 027/163] rm Text prop for now --- src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index 47c6e8f2d..277dedffd 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -5,11 +5,10 @@ import * as React from "react"; interface Props { name: string; viewUrl: string; - text?: string; }; export const SubscribeButton = (props: Props) => props.viewUrl - ? + ? : null; const buildButtonProps = (props: Props) => { From ab2feb5119aae2eaf74623c7086aaeeb9dd19ca5 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 20:46:24 -0500 Subject: [PATCH 028/163] use dashed for .onion --- src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index 277dedffd..f03f408dd 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -25,7 +25,7 @@ const buildButtonProps = (props: Props) => { // HTTP protocols case props.viewUrl.includes(".onion/"): - type = "ghost"; + type = "dashed"; title = defaultTitle("Tor address - "); break; case props.viewUrl.includes("http://"): From 71a933346a730aa923775340ec6ddf544891b6bc Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 20:49:54 -0500 Subject: [PATCH 029/163] explicitly define return types --- src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index f03f408dd..52ba6b3f6 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -1,17 +1,18 @@ import { Button } from 'antd'; import { ButtonProps, ButtonType } from "antd/lib/button"; import * as React from "react"; +import { JSXElement } from '@babel/types'; interface Props { name: string; viewUrl: string; }; -export const SubscribeButton = (props: Props) => props.viewUrl +export const SubscribeButton = (props: Props): JSX.Element | null => props.viewUrl ? : null; -const buildButtonProps = (props: Props) => { +const buildButtonProps = (props: Props): ButtonProps => { let type: ButtonType = "primary"; const hrefLocation = `${encodeURIComponent(props.viewUrl)}`; From b6065beeb4f55345ad733da4ea479b1e700885a0 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 20:54:42 -0500 Subject: [PATCH 030/163] enable noImplicitAny --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx | 1 - src/FilterLists.Web.V2/tsconfig.json | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 47fcd0f0e..035a12f61 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -27,7 +27,7 @@ export class AllListsTable extends React.Component<{}, State> { dataSource={this.state.data} rowKey={record => record.id.toString()} - loading={this.state.data.length == 0 ? true : false} + loading={this.state.data.length === 0 ? true : false} size="middle" pagination={{ position: "top", size: "small" }} > diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index 52ba6b3f6..e55a65ba5 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -1,7 +1,6 @@ import { Button } from 'antd'; import { ButtonProps, ButtonType } from "antd/lib/button"; import * as React from "react"; -import { JSXElement } from '@babel/types'; interface Props { name: string; diff --git a/src/FilterLists.Web.V2/tsconfig.json b/src/FilterLists.Web.V2/tsconfig.json index 755462aec..213390d38 100644 --- a/src/FilterLists.Web.V2/tsconfig.json +++ b/src/FilterLists.Web.V2/tsconfig.json @@ -17,7 +17,8 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "preserve" + "jsx": "preserve", + "noImplicitAny": true }, "include": [ "src" From 0cca088b8d6805447f58463998f262a42b9ba874 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 5 Aug 2019 20:55:51 -0500 Subject: [PATCH 031/163] revert to small table size --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 035a12f61..db141a530 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -28,7 +28,7 @@ export class AllListsTable extends React.Component<{}, State> { dataSource={this.state.data} rowKey={record => record.id.toString()} loading={this.state.data.length === 0 ? true : false} - size="middle" + size="small" pagination={{ position: "top", size: "small" }} > title="Name" From 4e3dd51efbcd427daa5c3bf3ae046b3db059ee1b Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 07:00:34 -0500 Subject: [PATCH 032/163] add dropdown to SubscribeButton --- .../modules/allListsTable/AllListsTable.tsx | 2 +- .../src/shared/SubscribeButton.tsx | 51 +++++++++++++------ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index db141a530..10c704a47 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -42,7 +42,7 @@ export class AllListsTable extends React.Component<{}, State> { dataIndex={nameof("viewUrl")} width={100} fixed="right" - render={(text: string, record: List, index: number) => } + render={(text: string, record: List, index: number) => } /> ); diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index e55a65ba5..f95f19546 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -1,50 +1,69 @@ -import { Button } from 'antd'; +import { Button, Dropdown, Icon, Menu } from 'antd'; import { ButtonProps, ButtonType } from "antd/lib/button"; import * as React from "react"; interface Props { name: string; viewUrl: string; + viewUrlMirrors: string[]; }; -export const SubscribeButton = (props: Props): JSX.Element | null => props.viewUrl - ? - : null; +export const SubscribeButton = (props: Props): JSX.Element | null => + (props.viewUrlMirrors && props.viewUrlMirrors.length > 0) + ? + : props.viewUrl + ? + : null; -const buildButtonProps = (props: Props): ButtonProps => { +const SubscribeButtonDropdown = (props: Props): JSX.Element => + + {props.viewUrlMirrors.map( + (viewUrlMirror: string, i: number) => + + + )} + + }> + + ; + +const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { let type: ButtonType = "primary"; - const hrefLocation = `${encodeURIComponent(props.viewUrl)}`; - const hrefTitle = `${encodeURIComponent(props.name)}`; + const hrefLocation = `${encodeURIComponent(viewUrl)}`; + const hrefTitle = `${encodeURIComponent(name)}`; let href = `abp:subscribe?location=${hrefLocation}&title=${hrefTitle}`; - const defaultTitle = (prefix?: string) => `${prefix || ""}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; + const defaultTitle = (prefix?: string) => `${prefix || ""}Subscribe to ${name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; let title: string; switch (true) { // HTTP protocols - case props.viewUrl.includes(".onion/"): + case viewUrl.includes(".onion/"): type = "dashed"; title = defaultTitle("Tor address - "); break; - case props.viewUrl.includes("http://"): + case viewUrl.includes("http://"): type = "danger"; title = defaultTitle("Not Secure - "); break; // Software protocols - case props.viewUrl.includes(".tpl"): + case viewUrl.includes(".tpl"): href = `javascript:window.external.msAddTrackingProtectionList('${hrefLocation}', '${hrefTitle}')`; - title = `Subscribe to ${props.name} with Internet Explorer's Tracking Protection List feature.`; + title = `Subscribe to ${name} with Internet Explorer's Tracking Protection List feature.`; break; - case props.viewUrl.includes(".lsrules"): + case viewUrl.includes(".lsrules"): href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; - title = `Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; + title = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; break; - case props.viewUrl.includes("?hostformat=littlesnitch"): + case viewUrl.includes("?hostformat=littlesnitch"): href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; - title = `Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; + title = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; break; default: title = defaultTitle(); From 7d67c231d47972cfbfc1f1f6acade19bae852764 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 08:34:18 -0500 Subject: [PATCH 033/163] refactor SubscribeButton dropdown --- .../modules/allListsTable/AllListsTable.tsx | 1 - .../src/shared/SubscribeButton.tsx | 35 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 10c704a47..537f05e91 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -40,7 +40,6 @@ export class AllListsTable extends React.Component<{}, State> { dataIndex={nameof("description")} /> title="Subscribe" dataIndex={nameof("viewUrl")} - width={100} fixed="right" render={(text: string, record: List, index: number) => } /> diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index f95f19546..d55ed6b4b 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -1,7 +1,11 @@ -import { Button, Dropdown, Icon, Menu } from 'antd'; +import { Button, Dropdown, Menu } from 'antd'; import { ButtonProps, ButtonType } from "antd/lib/button"; import * as React from "react"; +//TODO: import DropdownButtonType from antd rather than redefining if they export the type +//import { DropdownButtonType } from "antd/lib/dropdown"; +declare type DropdownButtonType = 'primary' | 'ghost' | 'dashed'; + interface Props { name: string; viewUrl: string; @@ -12,23 +16,26 @@ export const SubscribeButton = (props: Props): JSX.Element | null => (props.viewUrlMirrors && props.viewUrlMirrors.length > 0) ? : props.viewUrl - ? + ? : null; -const SubscribeButtonDropdown = (props: Props): JSX.Element => - - {props.viewUrlMirrors.map( - (viewUrlMirror: string, i: number) => +const SubscribeButtonDropdown = (props: Props): JSX.Element => { + var buttonProps = buildButtonProps(props.name, props.viewUrl); + //TODO: pass title (ref https://github.com/ant-design/ant-design/issues/18122) + return + {props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - + )} - - }> - - ; + + }> + Subscribe + ; +}; const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { let type: ButtonType = "primary"; From 092ec32e16df538cd77151bda886488629b54937 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 08:42:16 -0500 Subject: [PATCH 034/163] try definining title in span ref https://github.com/ant-design/ant-design/issues/18122#issuecomment-518672536 --- src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index d55ed6b4b..e72c441b0 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -33,8 +33,8 @@ const SubscribeButtonDropdown = (props: Props): JSX.Element => { )} }> - Subscribe - ; + Subscribe + ; }; const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { From e64c118df2a0db994896d1151815490be86b7bba Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 09:08:46 -0500 Subject: [PATCH 035/163] fix font color on dropdown buttons --- src/FilterLists.Web.V2/src/shared/SubscribeButton.css | 5 +++++ src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx | 1 + 2 files changed, 6 insertions(+) create mode 100644 src/FilterLists.Web.V2/src/shared/SubscribeButton.css diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.css b/src/FilterLists.Web.V2/src/shared/SubscribeButton.css new file mode 100644 index 000000000..33ae6340d --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.css @@ -0,0 +1,5 @@ +/* fix font color on dropdown buttons */ +.ant-dropdown-menu-item > a, +.ant-dropdown-menu-submenu-title > a { + color: #fff; +} diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index e72c441b0..679fd2d3f 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -1,6 +1,7 @@ import { Button, Dropdown, Menu } from 'antd'; import { ButtonProps, ButtonType } from "antd/lib/button"; import * as React from "react"; +import './SubscribeButton.css'; //TODO: import DropdownButtonType from antd rather than redefining if they export the type //import { DropdownButtonType } from "antd/lib/dropdown"; From ddf2a2d7341f39b4ba849f54bf278f25efb11bd3 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 09:11:44 -0500 Subject: [PATCH 036/163] rm some unused create-react-app boilerplate --- src/FilterLists.Web.V2/src/App.css | 0 src/FilterLists.Web.V2/src/App.tsx | 1 - src/FilterLists.Web.V2/src/index.tsx | 8 +- src/FilterLists.Web.V2/src/serviceWorker.ts | 143 -------------------- 4 files changed, 1 insertion(+), 151 deletions(-) delete mode 100644 src/FilterLists.Web.V2/src/App.css delete mode 100644 src/FilterLists.Web.V2/src/serviceWorker.ts diff --git a/src/FilterLists.Web.V2/src/App.css b/src/FilterLists.Web.V2/src/App.css deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index ba8fd2e0f..e655c23b2 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,6 +1,5 @@ import { Layout, Menu } from 'antd'; import React from 'react'; -import './App.css'; import { AllListsTable } from './modules'; const { Header, Content, Footer } = Layout; diff --git a/src/FilterLists.Web.V2/src/index.tsx b/src/FilterLists.Web.V2/src/index.tsx index 57a536ca7..c9a1418bf 100644 --- a/src/FilterLists.Web.V2/src/index.tsx +++ b/src/FilterLists.Web.V2/src/index.tsx @@ -2,11 +2,5 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import './index.css'; -import * as serviceWorker from './serviceWorker'; -ReactDOM.render(, document.getElementById('root')); - -// If you want your app to work offline and load faster, you can change -// unregister() to register() below. Note this comes with some pitfalls. -// Learn more about service workers: https://bit.ly/CRA-PWA -serviceWorker.unregister(); +ReactDOM.render(, document.getElementById('root')); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/serviceWorker.ts b/src/FilterLists.Web.V2/src/serviceWorker.ts deleted file mode 100644 index b3793f855..000000000 --- a/src/FilterLists.Web.V2/src/serviceWorker.ts +++ /dev/null @@ -1,143 +0,0 @@ -// This optional code is used to register a service worker. -// register() is not called by default. - -// This lets the app load faster on subsequent visits in production, and gives -// it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on subsequent visits to a page, after all the -// existing tabs open on the page have been closed, since previously cached -// resources are updated in the background. - -// To learn more about the benefits of this model and instructions on how to -// opt-in, read https://bit.ly/CRA-PWA - -const isLocalhost = Boolean( - window.location.hostname === 'localhost' || - // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || - // 127.0.0.1/8 is considered localhost for IPv4. - window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) -); - -type Config = { - onSuccess?: (registration: ServiceWorkerRegistration) => void; - onUpdate?: (registration: ServiceWorkerRegistration) => void; -}; - -export function register(config?: Config) { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { - // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL( - (process as { env: { [key: string]: string } }).env.PUBLIC_URL, - window.location.href - ); - if (publicUrl.origin !== window.location.origin) { - // Our service worker won't work if PUBLIC_URL is on a different origin - // from what our page is served on. This might happen if a CDN is used to - // serve assets; see https://github.com/facebook/create-react-app/issues/2374 - return; - } - - window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - - if (isLocalhost) { - // This is running on localhost. Let's check if a service worker still exists or not. - checkValidServiceWorker(swUrl, config); - - // Add some additional logging to localhost, pointing developers to the - // service worker/PWA documentation. - navigator.serviceWorker.ready.then(() => { - console.log( - 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://bit.ly/CRA-PWA' - ); - }); - } else { - // Is not localhost. Just register service worker - registerValidSW(swUrl, config); - } - }); - } -} - -function registerValidSW(swUrl: string, config?: Config) { - navigator.serviceWorker - .register(swUrl) - .then(registration => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - if (installingWorker == null) { - return; - } - installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { - if (navigator.serviceWorker.controller) { - // At this point, the updated precached content has been fetched, - // but the previous service worker will still serve the older - // content until all client tabs are closed. - console.log( - 'New content is available and will be used when all ' + - 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' - ); - - // Execute callback - if (config && config.onUpdate) { - config.onUpdate(registration); - } - } else { - // At this point, everything has been precached. - // It's the perfect time to display a - // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); - - // Execute callback - if (config && config.onSuccess) { - config.onSuccess(registration); - } - } - } - }; - }; - }) - .catch(error => { - console.error('Error during service worker registration:', error); - }); -} - -function checkValidServiceWorker(swUrl: string, config?: Config) { - // Check if the service worker can be found. If it can't reload the page. - fetch(swUrl) - .then(response => { - // Ensure service worker exists, and that we really are getting a JS file. - const contentType = response.headers.get('content-type'); - if ( - response.status === 404 || - (contentType != null && contentType.indexOf('javascript') === -1) - ) { - // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { - registration.unregister().then(() => { - window.location.reload(); - }); - }); - } else { - // Service worker found. Proceed as normal. - registerValidSW(swUrl, config); - } - }) - .catch(() => { - console.log( - 'No internet connection found. App is running in offline mode.' - ); - }); -} - -export function unregister() { - if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready.then(registration => { - registration.unregister(); - }); - } -} From 5906af845482f71f2239341950b7de2e15e45775 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 10:37:57 -0500 Subject: [PATCH 037/163] fix width of Subscribe column --- .../src/modules/allListsTable/AllListsTable.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 537f05e91..a0cef8284 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -40,6 +40,7 @@ export class AllListsTable extends React.Component<{}, State> { dataIndex={nameof("description")} /> title="Subscribe" dataIndex={nameof("viewUrl")} + width={123} fixed="right" render={(text: string, record: List, index: number) => } /> From 488b85855f8784608a23d5b2f965fd39557bac18 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 11:49:01 -0500 Subject: [PATCH 038/163] limit table cells from wrapping more than 2 lines --- .../src/modules/allListsTable/AllListsTable.css | 12 ++++++++++++ .../src/modules/allListsTable/AllListsTable.tsx | 9 ++++++--- .../src/shared/SubscribeButton.css | 4 ++++ 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css new file mode 100644 index 000000000..678542d7c --- /dev/null +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css @@ -0,0 +1,12 @@ +/* limit table cells from wrapping more than 2 lines */ +/* https://stackoverflow.com/a/13924997/2343739 */ +/* https://stackoverflow.com/a/22042054/2343739 */ +td > div { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + line-height: 1.5; + max-height: 3em; +} diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index a0cef8284..9a86cf2d8 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -2,6 +2,7 @@ import { Table } from 'antd'; import * as React from "react"; import { SubscribeButton } from '../../shared/'; import { nameof } from '../../utils'; +import './AllListsTable.css'; import { List } from './List'; interface State { @@ -34,15 +35,17 @@ export class AllListsTable extends React.Component<{}, State> { title="Name" dataIndex={nameof("name")} width={250} - fixed="left" /> + fixed="left" + render={(text: string) =>
{text}
} /> title="Description" - dataIndex={nameof("description")} /> + dataIndex={nameof("description")} + render={(text: string) =>
{text}
} /> title="Subscribe" dataIndex={nameof("viewUrl")} width={123} fixed="right" - render={(text: string, record: List, index: number) => } + render={(text: string, record: List, index: number) =>
} /> ); diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.css b/src/FilterLists.Web.V2/src/shared/SubscribeButton.css index 33ae6340d..db1b2b5e0 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.css +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.css @@ -3,3 +3,7 @@ .ant-dropdown-menu-submenu-title > a { color: #fff; } + +span { + z-index: 1000000; +} From 0dbcfd6987cb620b150e4f128f233d4e535f0ce1 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 11:50:13 -0500 Subject: [PATCH 039/163] chop long line --- .../src/modules/allListsTable/AllListsTable.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 9a86cf2d8..5af9d3d4e 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -45,7 +45,10 @@ export class AllListsTable extends React.Component<{}, State> { dataIndex={nameof("viewUrl")} width={123} fixed="right" - render={(text: string, record: List, index: number) =>
} + render={(text: string, record: List, index: number) => +
+ +
} /> ); From c17c4e7c0f41e607b1c8c1496283ea0974d06744 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 11:51:55 -0500 Subject: [PATCH 040/163] rm div-wrapper to chop long line from fixed-width button column --- .../src/modules/allListsTable/AllListsTable.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 5af9d3d4e..7e70bb905 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -46,9 +46,7 @@ export class AllListsTable extends React.Component<{}, State> { width={123} fixed="right" render={(text: string, record: List, index: number) => -
- -
} + } /> ); From 7199e80b76ff3ac10ad5ccc5fb4134ebf1d827c9 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 12:33:16 -0500 Subject: [PATCH 041/163] fixed row heights --- .../src/modules/allListsTable/AllListsTable.css | 7 ++++--- src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css index 678542d7c..26c847211 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css @@ -6,7 +6,8 @@ td > div { text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; - -webkit-line-clamp: 2; - line-height: 1.5; - max-height: 3em; + -webkit-line-clamp: 2; /* number of lines to show */ + line-height: 1.5; /* fallback */ + max-height: 3em; /* fallback */ + min-height: 3em; /* fixed row height */ } diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx index 679fd2d3f..815a445a3 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx @@ -17,7 +17,9 @@ export const SubscribeButton = (props: Props): JSX.Element | null => (props.viewUrlMirrors && props.viewUrlMirrors.length > 0) ? : props.viewUrl - ? + ?
+ +
: null; const SubscribeButtonDropdown = (props: Props): JSX.Element => { From 4621d2dd854d2aa26cb50e79f6a3ca8d44f8d013 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 13:02:26 -0500 Subject: [PATCH 042/163] clarify css comments --- .../src/modules/allListsTable/AllListsTable.css | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css index 26c847211..7aa63678d 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css @@ -1,7 +1,7 @@ -/* limit table cells from wrapping more than 2 lines */ -/* https://stackoverflow.com/a/13924997/2343739 */ -/* https://stackoverflow.com/a/22042054/2343739 */ td > div { + /* limit table cells from wrapping more than 2 lines */ + /* https://stackoverflow.com/a/13924997/2343739 */ + /* https://stackoverflow.com/a/22042054/2343739 */ overflow: hidden; text-overflow: ellipsis; display: -webkit-box; @@ -9,5 +9,7 @@ td > div { -webkit-line-clamp: 2; /* number of lines to show */ line-height: 1.5; /* fallback */ max-height: 3em; /* fallback */ - min-height: 3em; /* fixed row height */ + + /* fixed row height */ + min-height: 3em; } From e0dcb9f01ba996df7a030964fc817554e3c3f2f0 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 13:12:24 -0500 Subject: [PATCH 043/163] rm unused rule --- src/FilterLists.Web.V2/src/shared/SubscribeButton.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.css b/src/FilterLists.Web.V2/src/shared/SubscribeButton.css index db1b2b5e0..33ae6340d 100644 --- a/src/FilterLists.Web.V2/src/shared/SubscribeButton.css +++ b/src/FilterLists.Web.V2/src/shared/SubscribeButton.css @@ -3,7 +3,3 @@ .ant-dropdown-menu-submenu-title > a { color: #fff; } - -span { - z-index: 1000000; -} From 256c822ebc035cef0b7339a20cdb16e4d97b209d Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 13:19:25 -0500 Subject: [PATCH 044/163] tidies --- src/FilterLists.Web.V2/src/App.tsx | 5 ++--- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- src/FilterLists.Web.V2/src/shared/buttons/index.ts | 3 +++ .../src/shared/{ => buttons/subscribe}/SubscribeButton.css | 0 .../src/shared/{ => buttons/subscribe}/SubscribeButton.tsx | 0 src/FilterLists.Web.V2/src/shared/buttons/subscribe/index.ts | 3 +++ src/FilterLists.Web.V2/src/shared/index.ts | 2 +- 7 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/shared/buttons/index.ts rename src/FilterLists.Web.V2/src/shared/{ => buttons/subscribe}/SubscribeButton.css (100%) rename src/FilterLists.Web.V2/src/shared/{ => buttons/subscribe}/SubscribeButton.tsx (100%) create mode 100644 src/FilterLists.Web.V2/src/shared/buttons/subscribe/index.ts diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index e655c23b2..4764e2006 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -13,12 +13,11 @@ const App: React.FC = () => { theme="dark" mode="horizontal" style={{ lineHeight: '64px' }} - > - + />
- +
©2019 Collin M. Barrett
diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 7e70bb905..9aaf3d782 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,6 +1,6 @@ import { Table } from 'antd'; import * as React from "react"; -import { SubscribeButton } from '../../shared/'; +import { SubscribeButton } from '../../shared'; import { nameof } from '../../utils'; import './AllListsTable.css'; import { List } from './List'; diff --git a/src/FilterLists.Web.V2/src/shared/buttons/index.ts b/src/FilterLists.Web.V2/src/shared/buttons/index.ts new file mode 100644 index 000000000..a551734b5 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/buttons/index.ts @@ -0,0 +1,3 @@ +import { SubscribeButton } from './subscribe'; + +export { SubscribeButton } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.css b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css similarity index 100% rename from src/FilterLists.Web.V2/src/shared/SubscribeButton.css rename to src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css diff --git a/src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/shared/SubscribeButton.tsx rename to src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/index.ts b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/index.ts new file mode 100644 index 000000000..08f333155 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/index.ts @@ -0,0 +1,3 @@ +import { SubscribeButton } from './SubscribeButton'; + +export { SubscribeButton } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/index.ts b/src/FilterLists.Web.V2/src/shared/index.ts index 08f333155..fc3bfe9e8 100644 --- a/src/FilterLists.Web.V2/src/shared/index.ts +++ b/src/FilterLists.Web.V2/src/shared/index.ts @@ -1,3 +1,3 @@ -import { SubscribeButton } from './SubscribeButton'; +import { SubscribeButton } from './buttons'; export { SubscribeButton } \ No newline at end of file From ea666720e534667c6b7dcb8e9608bee715f3265a Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 13:40:05 -0500 Subject: [PATCH 045/163] match single Subscribe button with dropdown width --- .../src/shared/buttons/subscribe/SubscribeButton.css | 4 ++++ .../src/shared/buttons/subscribe/SubscribeButton.tsx | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css index 33ae6340d..a8c70d68a 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css @@ -3,3 +3,7 @@ .ant-dropdown-menu-submenu-title > a { color: #fff; } + +.ant-btn.single { + width: 106.81px; +} diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index 815a445a3..c6c6185c9 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -18,7 +18,7 @@ export const SubscribeButton = (props: Props): JSX.Element | null => ? : props.viewUrl ?
- +
: null; From 4f7aa6bf725253e7b6ae243875d89c64f0c9b7dc Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 13:40:58 -0500 Subject: [PATCH 046/163] rm not working span for tooltip for now ref https://github.com/ant-design/ant-design/issues/18122 --- .../src/shared/buttons/subscribe/SubscribeButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index c6c6185c9..879a30a66 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -36,7 +36,7 @@ const SubscribeButtonDropdown = (props: Props): JSX.Element => { )} }> - Subscribe + Subscribe ; }; From 27e57e8b82bf00256abb5cd27eb10b96a9beb119 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 14:04:22 -0500 Subject: [PATCH 047/163] fixed row heights --- .../src/modules/allListsTable/AllListsTable.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css index 7aa63678d..7c35b9e45 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css @@ -4,7 +4,7 @@ td > div { /* https://stackoverflow.com/a/22042054/2343739 */ overflow: hidden; text-overflow: ellipsis; - display: -webkit-box; + display: -webkit-box !important; /* TODO: refactor out important */ -webkit-box-orient: vertical; -webkit-line-clamp: 2; /* number of lines to show */ line-height: 1.5; /* fallback */ From f785dcf8a8eea794fdc6e68c2198ee4170dca996 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 14:14:58 -0500 Subject: [PATCH 048/163] show page sizer --- .../src/modules/allListsTable/AllListsTable.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 9aaf3d782..4337afb74 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -30,7 +30,12 @@ export class AllListsTable extends React.Component<{}, State> { rowKey={record => record.id.toString()} loading={this.state.data.length === 0 ? true : false} size="small" - pagination={{ position: "top", size: "small" }} > + pagination={{ + size: "small", + defaultPageSize: 12, + showSizeChanger: true, + pageSizeOptions: ["6", "12", "2000"] + }} > title="Name" dataIndex={nameof("name")} From 1831cf2cd372969e3453fb9417897bfcffb51cbd Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 14:16:20 -0500 Subject: [PATCH 049/163] rm content padding to save space on smaller screens --- src/FilterLists.Web.V2/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 4764e2006..08ecc254f 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -15,7 +15,7 @@ const App: React.FC = () => { style={{ lineHeight: '64px' }} /> - +
From 11b87af302bed100e6047077aa7686ca76216da7 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 14:48:19 -0500 Subject: [PATCH 050/163] dynamic pageSize --- .../modules/allListsTable/AllListsTable.tsx | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 4337afb74..ad4980088 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -7,22 +7,42 @@ import { List } from './List'; interface State { data: List[]; + pageSize: number; + pageSizeOptions: string[]; } export class AllListsTable extends React.Component<{}, State> { constructor(props: any) { super(props); this.state = { - data: [] + data: [], + pageSize: 0, + pageSizeOptions: [] }; + this.updatePageSize = this.updatePageSize.bind(this); } componentDidMount() { + this.updatePageSize(); + window.addEventListener('resize', this.updatePageSize); + fetch("/api/v1/lists") .then(response => response.json()) .then(json => { this.setState({ data: json }); }) } + componentWillUnmount() { + window.removeEventListener('resize', this.updatePageSize); + } + + updatePageSize() { + const pageSize = Math.floor((window.innerHeight - 450) / 42); + this.setState({ + pageSize: pageSize, + pageSizeOptions: [5, 10, 20, 500, 2000, pageSize].sort((a, b) => a - b).map(String) + }); + } + render() { return ( @@ -32,9 +52,9 @@ export class AllListsTable extends React.Component<{}, State> { size="small" pagination={{ size: "small", - defaultPageSize: 12, + pageSize: this.state.pageSize, showSizeChanger: true, - pageSizeOptions: ["6", "12", "2000"] + pageSizeOptions: this.state.pageSizeOptions }} > title="Name" From 0d3e659dc90453c71bba24da4bc43277608471d4 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 15:58:13 -0500 Subject: [PATCH 051/163] fix math for auto-pageSize --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index ad4980088..293f9330a 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -36,7 +36,7 @@ export class AllListsTable extends React.Component<{}, State> { } updatePageSize() { - const pageSize = Math.floor((window.innerHeight - 450) / 42); + const pageSize = Math.floor((window.innerHeight - 275.5) / 59); this.setState({ pageSize: pageSize, pageSizeOptions: [5, 10, 20, 500, 2000, pageSize].sort((a, b) => a - b).map(String) From 8cac552254d1e139db6af8281afa831caf9f307a Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 16:02:07 -0500 Subject: [PATCH 052/163] tidies --- src/FilterLists.Web.V2/README.md | 44 ------------------- src/FilterLists.Web.V2/package.json | 3 +- .../buttons/subscribe/SubscribeButton.css | 1 + 3 files changed, 2 insertions(+), 46 deletions(-) delete mode 100644 src/FilterLists.Web.V2/README.md diff --git a/src/FilterLists.Web.V2/README.md b/src/FilterLists.Web.V2/README.md deleted file mode 100644 index 897dc8366..000000000 --- a/src/FilterLists.Web.V2/README.md +++ /dev/null @@ -1,44 +0,0 @@ -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). - -## Available Scripts - -In the project directory, you can run: - -### `npm start` - -Runs the app in the development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will reload if you make edits.
-You will also see any lint errors in the console. - -### `npm test` - -Launches the test runner in the interactive watch mode.
-See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `npm run build` - -Builds the app for production to the `build` folder.
-It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `npm run eject` - -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** - -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. - -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). diff --git a/src/FilterLists.Web.V2/package.json b/src/FilterLists.Web.V2/package.json index 9554ac1bc..c926d0479 100644 --- a/src/FilterLists.Web.V2/package.json +++ b/src/FilterLists.Web.V2/package.json @@ -19,8 +19,7 @@ "scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", - "test": "react-app-rewired test", - "eject": "react-scripts eject" + "test": "react-app-rewired test" }, "proxy": "https://filterlists.com", "eslintConfig": { diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css index a8c70d68a..3106850cc 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css @@ -4,6 +4,7 @@ color: #fff; } +/* make non-dropdown button equivalent width to dropdown */ .ant-btn.single { width: 106.81px; } From e205a958c3efcfbad49ac47e763e0082da711944 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 6 Aug 2019 16:17:42 -0500 Subject: [PATCH 053/163] responsive layout tweaks --- .../src/modules/allListsTable/AllListsTable.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 293f9330a..24b485c2a 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -9,6 +9,7 @@ interface State { data: List[]; pageSize: number; pageSizeOptions: string[]; + isNarrowWindow: boolean; } export class AllListsTable extends React.Component<{}, State> { @@ -17,7 +18,8 @@ export class AllListsTable extends React.Component<{}, State> { this.state = { data: [], pageSize: 0, - pageSizeOptions: [] + pageSizeOptions: [], + isNarrowWindow: false }; this.updatePageSize = this.updatePageSize.bind(this); } @@ -39,7 +41,8 @@ export class AllListsTable extends React.Component<{}, State> { const pageSize = Math.floor((window.innerHeight - 275.5) / 59); this.setState({ pageSize: pageSize, - pageSizeOptions: [5, 10, 20, 500, 2000, pageSize].sort((a, b) => a - b).map(String) + pageSizeOptions: [5, 10, 20, 500, 2000, pageSize].sort((a, b) => a - b).map(String), + isNarrowWindow: window.innerWidth < 576 ? true : false }); } @@ -55,11 +58,12 @@ export class AllListsTable extends React.Component<{}, State> { pageSize: this.state.pageSize, showSizeChanger: true, pageSizeOptions: this.state.pageSizeOptions - }} > + }} + scroll={{ x: this.state.isNarrowWindow ? 576 : 1600 }}> title="Name" dataIndex={nameof("name")} - width={250} + width={200} fixed="left" render={(text: string) =>
{text}
} /> @@ -69,7 +73,7 @@ export class AllListsTable extends React.Component<{}, State> { title="Subscribe" dataIndex={nameof("viewUrl")} width={123} - fixed="right" + fixed={this.state.isNarrowWindow ? undefined : "right"} render={(text: string, record: List, index: number) => } /> From 85a1ea09a0524913523dd132402f31b410429a9f Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 12:20:43 -0500 Subject: [PATCH 054/163] stub software, language, and tag columns --- .../src/modules/allListsTable/AllListsTable.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 24b485c2a..8f7298019 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -70,6 +70,18 @@ export class AllListsTable extends React.Component<{}, State> { title="Description" dataIndex={nameof("description")} render={(text: string) =>
{text}
} /> + + title="Software" + dataIndex={nameof("syntaxId")} + render={(text: string) =>
{text}
} /> + + title="Languages" + dataIndex={nameof("languageIds")} + render={(text: string) =>
{text}
} /> + + title="Tags" + dataIndex={nameof("tagIds")} + render={(text: string) =>
{text}
} /> title="Subscribe" dataIndex={nameof("viewUrl")} width={123} From a44aa3a179594e26a9a03b00284300809f914bb0 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 12:28:09 -0500 Subject: [PATCH 055/163] HTML5 cite quoted Descriptions --- .../src/modules/allListsTable/AllListsTable.tsx | 4 ++-- src/FilterLists.Web.V2/src/shared/Description.tsx | 11 +++++++++++ src/FilterLists.Web.V2/src/shared/index.ts | 4 +++- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/shared/Description.tsx diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 8f7298019..50ac3ae6e 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,6 +1,6 @@ import { Table } from 'antd'; import * as React from "react"; -import { SubscribeButton } from '../../shared'; +import { SubscribeButton, Description } from '../../shared'; import { nameof } from '../../utils'; import './AllListsTable.css'; import { List } from './List'; @@ -69,7 +69,7 @@ export class AllListsTable extends React.Component<{}, State> { title="Description" dataIndex={nameof("description")} - render={(text: string) =>
{text}
} /> + render={(text: string, record: List) => } /> title="Software" dataIndex={nameof("syntaxId")} diff --git a/src/FilterLists.Web.V2/src/shared/Description.tsx b/src/FilterLists.Web.V2/src/shared/Description.tsx new file mode 100644 index 000000000..ec7a2d3c4 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/Description.tsx @@ -0,0 +1,11 @@ +import * as React from "react"; + +interface Props { + desription: string; + desriptionSourceUrl: string; +}; + +export const Description = (props: Props): JSX.Element | null => + props.desriptionSourceUrl + ?
{props.desription}
+ :

{props.desription}

; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/index.ts b/src/FilterLists.Web.V2/src/shared/index.ts index fc3bfe9e8..55147fbd6 100644 --- a/src/FilterLists.Web.V2/src/shared/index.ts +++ b/src/FilterLists.Web.V2/src/shared/index.ts @@ -1,3 +1,5 @@ import { SubscribeButton } from './buttons'; +import { Description } from './Description'; -export { SubscribeButton } \ No newline at end of file +export { SubscribeButton }; +export { Description }; From 4157bc89c6b639ec4b5e0cf22f2f4b920133b165 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 12:31:37 -0500 Subject: [PATCH 056/163] line break tidy --- .../src/modules/allListsTable/AllListsTable.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 50ac3ae6e..5d89dc01d 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -69,7 +69,8 @@ export class AllListsTable extends React.Component<{}, State> { title="Description" dataIndex={nameof("description")} - render={(text: string, record: List) => } /> + render={(text: string, record: List) => + } /> title="Software" dataIndex={nameof("syntaxId")} @@ -87,8 +88,7 @@ export class AllListsTable extends React.Component<{}, State> { width={123} fixed={this.state.isNarrowWindow ? undefined : "right"} render={(text: string, record: List, index: number) => - } - /> + } /> ); } From 6d62e24ca4d5acc3cbe2690b77492a6911cfb2b1 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 12:38:04 -0500 Subject: [PATCH 057/163] apply two-line max to cells with nested blockquote or p --- .../src/modules/allListsTable/AllListsTable.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css index 7c35b9e45..17211aa65 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css @@ -1,4 +1,6 @@ -td > div { +td > div, +td > blockquote, +td > p { /* limit table cells from wrapping more than 2 lines */ /* https://stackoverflow.com/a/13924997/2343739 */ /* https://stackoverflow.com/a/22042054/2343739 */ From e6d1827e4887861ad959df6e68e5b301c8c8db86 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 12:52:07 -0500 Subject: [PATCH 058/163] add sort to Name column --- .../src/modules/allListsTable/AllListsTable.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 5d89dc01d..afa17c83f 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -63,6 +63,8 @@ export class AllListsTable extends React.Component<{}, State> { title="Name" dataIndex={nameof("name")} + sorter={(a, b) => a.name.localeCompare(b.name)} + defaultSortOrder={"ascend"} width={200} fixed="left" render={(text: string) =>
{text}
} /> From 455b5a24f1dad0d5e2935a2c345ee7d800f7ae56 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 13:04:17 -0500 Subject: [PATCH 059/163] copy over public resources --- src/FilterLists.Web.V2/public/favicon.ico | Bin 3870 -> 0 bytes .../public/icon_filterlists.png | Bin 0 -> 2163 bytes src/FilterLists.Web.V2/public/index.html | 55 +++++++----------- .../public/logo_filterlists.png | Bin 0 -> 3953 bytes src/FilterLists.Web.V2/public/manifest.json | 8 +-- 5 files changed, 26 insertions(+), 37 deletions(-) delete mode 100644 src/FilterLists.Web.V2/public/favicon.ico create mode 100644 src/FilterLists.Web.V2/public/icon_filterlists.png create mode 100644 src/FilterLists.Web.V2/public/logo_filterlists.png diff --git a/src/FilterLists.Web.V2/public/favicon.ico b/src/FilterLists.Web.V2/public/favicon.ico deleted file mode 100644 index a11777cc471a4344702741ab1c8a588998b1311a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/src/FilterLists.Web.V2/public/icon_filterlists.png b/src/FilterLists.Web.V2/public/icon_filterlists.png new file mode 100644 index 0000000000000000000000000000000000000000..99c15bdde8dc8d089b942715967f19ba58848f0b GIT binary patch literal 2163 zcmc&#YgAKL7C!eHB*8+lI!ihNrBaG*ja(lPOcWD&M5-ZBd88l`h9WjJi4jN&7;-I6 z?F`t|KGYg{_@YW0o+}WNNyx%coKcu+jMzK~9ohg13D`=ogvZ==e$9{m(ABl({Mp~$ zd+l#O&OYn>B{hZa@ApSP0Dyn;?u54hfH4RIJPs2F1i=DK;EHGr8UXFm74!K%m>yQJ z`z;0l6|Vw-9tU6!Goj-Elpz2(*Z`2v0|zkM7}?=>mQhxlUA%K7$+e^ZghPKQ%UIsR=L zDp17D;p@|xA^4!5Rx{2R7}`&djS;y2;e~A(|{+opP%rT|9Fs{6iuKKF}7@+J{g~)C+=k53DMuAu~XMV zSLF`%6;n5#pEMcc-94e%f(y z2u_u>gw8ZxV~}7yfLPreTRGpSaWS>d(}qKj!KqW~Ky)s*%#yrM7SjSD`e-ym?#Wf- zSuh42v9(Fbn3=$*9+5Km@5!sos&CtQ<|7Msg@8* z0nE9=yxBr|lQ5j`bE0EwH{T!{(7LXGT8Ao9Y~*`S)}Zk&Fr0@w`mj*qWPzL7<+t6jHzD;L>VLu@l1GXbtKz1_-4@k!IQRcH$46F{CCq- z{C%I{1Gam$!KKqb?Cj=nBc9_}o69G0c>TS9V&u(<;AYos#cp~YNKzIXGRCmvgBs2j zkNHCX@FGt$Sr%1!H(dzF*UcMsXSD7P1vU@$kak?gX@5ER&?DOcug$}Vs<0|S?OL=` z=Tear=S<2~=*uud!bX_q?b-qb4P_K9T;WRi*87>@LxTREPKM2WQ2hcb5P{Znn#n|G zlaTAf{s?RsaA_uTi?kiff`%AVrm|syToVGqRaWRdwc}z9?`F$)w@zm&vXv@)?EUi+ z$;!j#CWh?P)Uv%zeJ2RtC5^B;tCskZXIn#{rz1c6#X%)|i%fHepzA@B$F4K1$ zvRd|+AuHbFslBdV_eGM{;pG@k#zz7R6U0r`RNXaHJrKz48voh+Nzi2XxYQFJLtjb^)Pz&WH-*2YU(HiHss^@MLT&#hJmUOf?T2`|7XFnYs^{>jA&gnkIYTyA~yB z-P|>~%Jvm)%bs!Pez&kEQS+;AY&+eTPhhRUNFz!US*7pfmll!>juc`7Y(_S1BO - - - - - - - - - React App - - - -
- - - + \ No newline at end of file diff --git a/src/FilterLists.Web.V2/public/logo_filterlists.png b/src/FilterLists.Web.V2/public/logo_filterlists.png new file mode 100644 index 0000000000000000000000000000000000000000..7d8d1817038c2ed8604825a8b526e2def1bb3e7f GIT binary patch literal 3953 zcmcIn`8(8Y7at;HW^6UcuA+t+vWD!klYRJR|JozVcr1lPX6#Fr#@b_hNM`7pB4lf9 zAzP2^sZ5q^Mb?yFz1RCMyuY05T=#v>=UnH$&hC&|LhfDOTqfWcsFMuxgpFc>3n z?5Dz+jxEAP!~h24P&U%lwz)OE{xC8G{Z6R2oi)~wcAg0r$jvEvHWT&%%4* zjF!rYNzjqPyp6N(htT^ZR6VFpWGqvgJ<9AG z^msP)uy^kL)YR9dBj)_br5Afjhf}v_n|MWuoI3Ec|3}lvB4vHLV1!7fR6t7bv!f-a znSPX&CP^v1dX$R_b3jMST)CmMN>TJM*UkL$z1z!jzSPQoZjexn;q!##l?fiiFt`~ zu?^xo^q~aKoXea~oN$pkzF$P!LT~0+o(iWm1I5X@-Jjkw=9X}r)E4EvGs1U``)|C* zM@Kxqb4u(ZFc1V(G$-U(ZoB-0i>7wlZGJ z$cs5;?vtcOH$s?arL(yZvUp$}KU! z_ANJ-#57)+EDLdi*ZXV+&6WB5EK7%XEUrg)foolojv2e;X@s}_%k6?9q1r~nSvbW| z824TX=@1@1ICx0UL?S@^?`&fH%=*yDNL$-kBq81gy!>i@zaM*mt7+WCeS>=yaZ>rYIM9(oD z$LrYS=}{ImSrU}8zCdN&uhvi7`=+)*V?r5d)Y6pSblVHc{QQOEDRi`}GzQ{_ZAL^A z?)A)^KS_LGNB{W^-QX^9!JTP~z+Br|1CZ1epKq$@8;F%h6T|~~O}af~bv~zH-!k^# zWeW65pfNa>r2>=fiIn^dhQl3DcQ-E;a;}9dH1$j@!pUwh##YxkL1rMqim0pBV zRWl&@GGn#}PFCVKnYLVKO?WRaJI)gGJ@8+E5A;dZ5c zK*GhKliU~LuPFCbEi@jzmEK`3($=#~Wecs!2vIO-Mj9g(5C_a9P&MBo0Hk;#RfA$l z5lD|#%>o`B0LSv3XwSZC}8#e23fXlK1&{&#Zad z_&e6RF{RUSLyaXxohF&UGa`)^MGtQ zS;bYNClC4X0=bk%`}Eqh=qW8w&lI?uT^~pYi4Id+E=lqQ(|Rc1D%M;kaFwLcgtm7t zjC+!2hO4F<9lL`%DO{t{TpFELEjF!%q<1{O|6SeC&#EyeC)PwDQ%qU?*vvZZlzY51 zoArPnS5K^Imr;lnm!%N{LbU$5ilmh+Dc5?BE-G{+xjHSPydT+0`sH&|2YB?+WXjU= zQV(gTuI=4raoNc~sK$zayG#LJU<{7H}vXXvss{GWLId zf6?1LO#jPzOUmc_v>$|PN*r*Cs@dwyos1*tQ~w3doelX=73Cd(wiP(|v6;fI>2z0R z2LJLtEn)02GjQm5kGo;W$suGcgcm_#+Ni0NBka#okhXU8YcS3gB(rH>?lLJ8a zXcfTV#A($nhAk%}QNH`M#@)~yBDYL!*-!{0X~7F*%i8g>1p0~0Fp0dtTbngvpJ!{2 zX{n~s%2+bXhZ!-@N?SSi;YwsO%}Npn%ku#E+d9N)TPYMM#9Q5)x8368V1pfftOBTQe_js|# zpbo;M35q#fc*)HBav6pE<>|xEa7S`Kd4>NztmO!gCafCP$JU zBuYgLilE!ev_Xarc+=SR%0go3gH)4&?Ufhm3_BJdLX3jxb?IoH7^Auk#y3)2wh*6+H4G3D`dWHkT+@ zJNVd{d%Obkieq26*EEN&oam6L3rd_CU)cI~RG9XC*QY{Pwiyb>JCNg$2O-scLR_&{*C#^Qm0zY+);w zDm>|>4Se{-jxfoGg8xDNUC%w^lm95LA+YrY>gf;{i5Zv0p?n21R5jRW8}_XZYOv=V zw?vqfLegCm!3*T?H}&@NK*pS1vfo6nzcQ25@=f#OpQe`VQECLw^x!Mj)&)F5enqr4 z6%Qlnfsc7@v!YgyaMF~&C^@3ov5J1hk~_C})p5eC6%m6=aZybz;?(pXr=DLbN&7PJ zs=6^F{}!bqKwqdEKSrXJLFdlmT$9$mNQJ7UwW41>J)c-NT{;`Ypvlc936v`Xu#?kN+2tzewr9?0bibRbBi4U>B#6F%g?Fcx?9lj^MHN~W-Shvd{+!GX{ zCx0MNOk7+}#u7w!$0xV`O653UMzuplxke50J6N@a3A;Ua%oToT-++5A?qb3dm)=(Y zeIPD5u!zJOzSr}^fqJ8!>5ywmv(HU_By007jS*doWS@fmf9~TrBo6UhckMP|S;VD}W@h&$*Ihxil zH2KF@+)?NOF@6g5X@O~MQ6LE9(Tbj<*D;n!nA_DZ1c@rIM ze)SrKbrPV{h5<8BX>n5c{i0a8Bt2RExs8;yfNLFU?1ztkJ=2Rj@mrS*s&EUrlA499 z7vhsZx4cG21@Eo?4mmo*)kHb#@)N#pH>R6WuH& z6-tw?%}WrTJW{{gKUDvtmF literal 0 HcmV?d00001 diff --git a/src/FilterLists.Web.V2/public/manifest.json b/src/FilterLists.Web.V2/public/manifest.json index 1f2f141fa..452af93c5 100644 --- a/src/FilterLists.Web.V2/public/manifest.json +++ b/src/FilterLists.Web.V2/public/manifest.json @@ -1,11 +1,11 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "FilterLists", + "name": "FilterLists | Subscriptions for uBlock Origin, Adblock Plus, AdGuard, ...", "icons": [ { - "src": "favicon.ico", + "src": "icon_filterlists.png", "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" + "type": "image/png" } ], "start_url": ".", From 5a0a243b6cf5d94318bc05db50470288619c72f5 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 13:07:31 -0500 Subject: [PATCH 060/163] mark method as private --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index afa17c83f..1e0b19860 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -37,7 +37,7 @@ export class AllListsTable extends React.Component<{}, State> { window.removeEventListener('resize', this.updatePageSize); } - updatePageSize() { + private updatePageSize() { const pageSize = Math.floor((window.innerHeight - 275.5) / 59); this.setState({ pageSize: pageSize, From 3cf55967cef8c34fa26b4c30eb728607884ac17d Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 15:14:01 -0500 Subject: [PATCH 061/163] implement TagCloud column --- src/FilterLists.Web.V2/package-lock.json | Bin 542414 -> 541902 bytes .../modules/allListsTable/AllListsTable.tsx | 33 ++++++++++++------ .../src/modules/allListsTable/Tag.ts | 6 ++++ .../src/shared/TagCloud.tsx | 20 +++++++++++ src/FilterLists.Web.V2/src/shared/index.ts | 4 +-- 5 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/Tag.ts create mode 100644 src/FilterLists.Web.V2/src/shared/TagCloud.tsx diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index c6c1284cc9249255342a3c76d7c9c5956fbdb3c0..e0870e3995c5362c48ab202aa61b9c1aa346d724 100644 GIT binary patch delta 271 zcmX@tt9Y(cv7v>rg{g&k3yW3wbO|LU+39lJOq|;r!dci@rb|S#$WPCYV&R^CA)4hT zn7dt;jcEoqMCINLmJidondG)B2s3Fjf>_h%MY0G@pDn`F2vKoCgo$PPK29d~>H0Y= zL14A}b6Dnq)o#Ba&ScL4QYSavSAppnSigZFljZhRicEmJiZTp^XcA?z>*0oSW delta 86 zcmX@tsd%nev7v>rg{g&k3yW3w^bNvHw$tUfnK-v6gtM@*K={5pF diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 1e0b19860..cd267daf3 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,12 +1,14 @@ import { Table } from 'antd'; import * as React from "react"; -import { SubscribeButton, Description } from '../../shared'; +import { Description, SubscribeButton, TagCloud } from '../../shared'; import { nameof } from '../../utils'; import './AllListsTable.css'; import { List } from './List'; +import { Tag } from './Tag'; interface State { - data: List[]; + lists: List[]; + tags: Tag[]; pageSize: number; pageSizeOptions: string[]; isNarrowWindow: boolean; @@ -16,7 +18,8 @@ export class AllListsTable extends React.Component<{}, State> { constructor(props: any) { super(props); this.state = { - data: [], + lists: [], + tags: [], pageSize: 0, pageSizeOptions: [], isNarrowWindow: false @@ -25,18 +28,27 @@ export class AllListsTable extends React.Component<{}, State> { } componentDidMount() { + this.fetchData(); this.updatePageSize(); window.addEventListener('resize', this.updatePageSize); - - fetch("/api/v1/lists") - .then(response => response.json()) - .then(json => { this.setState({ data: json }); }) } componentWillUnmount() { window.removeEventListener('resize', this.updatePageSize); } + private fetchData() { + fetch("/api/v1/lists") + .then(response => response.json()) + .then(json => (json as List[]).sort((a, b) => a.name.localeCompare(b.name))) + .then(lists => { this.setState({ lists: lists }); }) + + fetch("/api/v1/tags") + .then(response => response.json()) + .then(json => (json as Tag[]).sort((a, b) => a.name.localeCompare(b.name))) + .then(tags => { this.setState({ tags: tags }); }) + } + private updatePageSize() { const pageSize = Math.floor((window.innerHeight - 275.5) / 59); this.setState({ @@ -49,9 +61,9 @@ export class AllListsTable extends React.Component<{}, State> { render() { return ( - dataSource={this.state.data} + dataSource={this.state.lists} rowKey={record => record.id.toString()} - loading={this.state.data.length === 0 ? true : false} + loading={this.state.lists.length === 0 ? true : false} size="small" pagination={{ size: "small", @@ -84,7 +96,8 @@ export class AllListsTable extends React.Component<{}, State> { title="Tags" dataIndex={nameof("tagIds")} - render={(text: string) =>
{text}
} /> + render={(tagIds: number[]) => + tagIds.includes(t.id))} />} /> title="Subscribe" dataIndex={nameof("viewUrl")} width={123} diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/Tag.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/Tag.ts new file mode 100644 index 000000000..755e683f7 --- /dev/null +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/Tag.ts @@ -0,0 +1,6 @@ +export interface Tag { + id: number; + description: string; + filterListIds: number[]; + name: string; +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/TagCloud.tsx b/src/FilterLists.Web.V2/src/shared/TagCloud.tsx new file mode 100644 index 000000000..2a8bf3400 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/TagCloud.tsx @@ -0,0 +1,20 @@ +import { Tag } from 'antd'; +import * as React from "react"; + +interface TagData { + description: string; + name: string; +}; + +interface Props { + tags?: TagData[] +}; + +export const TagCloud = (props: Props): JSX.Element | null => { + return props.tags + ?
+ {props.tags.map((t: TagData, i: number) => + {t.name})} +
+ : null; +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/index.ts b/src/FilterLists.Web.V2/src/shared/index.ts index 55147fbd6..4d83351b7 100644 --- a/src/FilterLists.Web.V2/src/shared/index.ts +++ b/src/FilterLists.Web.V2/src/shared/index.ts @@ -1,5 +1,5 @@ import { SubscribeButton } from './buttons'; import { Description } from './Description'; +import { TagCloud } from './TagCloud'; -export { SubscribeButton }; -export { Description }; +export { SubscribeButton, Description, TagCloud }; From 32e137ec1beb294a7b52f8c044334554aba2c121 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 15:18:38 -0500 Subject: [PATCH 062/163] viewUrl is always required and should never be null/undefined --- .../src/shared/buttons/subscribe/SubscribeButton.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index 879a30a66..fc7afd0ff 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -13,14 +13,12 @@ interface Props { viewUrlMirrors: string[]; }; -export const SubscribeButton = (props: Props): JSX.Element | null => +export const SubscribeButton = (props: Props): JSX.Element => (props.viewUrlMirrors && props.viewUrlMirrors.length > 0) ? - : props.viewUrl - ?
- -
- : null; + :
+ +
; const SubscribeButtonDropdown = (props: Props): JSX.Element => { var buttonProps = buildButtonProps(props.name, props.viewUrl); From 8f93fe1368a7cebffc1902619dd49af0757985c9 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 15:19:04 -0500 Subject: [PATCH 063/163] handle lists with no tags --- .../src/modules/allListsTable/AllListsTable.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index cd267daf3..eea48f5b0 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -96,8 +96,9 @@ export class AllListsTable extends React.Component<{}, State> { title="Tags" dataIndex={nameof("tagIds")} + width={200} render={(tagIds: number[]) => - tagIds.includes(t.id))} />} /> + tagIds ? tagIds.includes(t.id))} /> : null} /> title="Subscribe" dataIndex={nameof("viewUrl")} width={123} From 4f2e2e7c3620155621c6622a37cd93862e3b4bd0 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 15:51:50 -0500 Subject: [PATCH 064/163] allow tags to vertically grow, start using module-scoped css --- .../src/modules/allListsTable/AllListsTable.css | 4 +--- src/FilterLists.Web.V2/src/shared/index.ts | 2 +- .../src/shared/tagCloud/TagCloud.module.css | 3 +++ src/FilterLists.Web.V2/src/shared/{ => tagCloud}/TagCloud.tsx | 3 ++- src/FilterLists.Web.V2/src/shared/tagCloud/index.ts | 3 +++ 5 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css rename src/FilterLists.Web.V2/src/shared/{ => tagCloud}/TagCloud.tsx (82%) create mode 100644 src/FilterLists.Web.V2/src/shared/tagCloud/index.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css index 17211aa65..5a637ae03 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css @@ -1,6 +1,4 @@ -td > div, -td > blockquote, -td > p { +td > * { /* limit table cells from wrapping more than 2 lines */ /* https://stackoverflow.com/a/13924997/2343739 */ /* https://stackoverflow.com/a/22042054/2343739 */ diff --git a/src/FilterLists.Web.V2/src/shared/index.ts b/src/FilterLists.Web.V2/src/shared/index.ts index 4d83351b7..7ed61c7b7 100644 --- a/src/FilterLists.Web.V2/src/shared/index.ts +++ b/src/FilterLists.Web.V2/src/shared/index.ts @@ -1,5 +1,5 @@ import { SubscribeButton } from './buttons'; import { Description } from './Description'; -import { TagCloud } from './TagCloud'; +import { TagCloud } from './tagCloud'; export { SubscribeButton, Description, TagCloud }; diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css new file mode 100644 index 000000000..42f8db99a --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css @@ -0,0 +1,3 @@ +.grow { + max-height: none !important; +} diff --git a/src/FilterLists.Web.V2/src/shared/TagCloud.tsx b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx similarity index 82% rename from src/FilterLists.Web.V2/src/shared/TagCloud.tsx rename to src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx index 2a8bf3400..6d38c971d 100644 --- a/src/FilterLists.Web.V2/src/shared/TagCloud.tsx +++ b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx @@ -1,5 +1,6 @@ import { Tag } from 'antd'; import * as React from "react"; +import styles from './TagCloud.module.css'; interface TagData { description: string; @@ -12,7 +13,7 @@ interface Props { export const TagCloud = (props: Props): JSX.Element | null => { return props.tags - ?
+ ?
{props.tags.map((t: TagData, i: number) => {t.name})}
diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/index.ts b/src/FilterLists.Web.V2/src/shared/tagCloud/index.ts new file mode 100644 index 000000000..1e8216050 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/tagCloud/index.ts @@ -0,0 +1,3 @@ +import { TagCloud } from './TagCloud'; + +export { TagCloud }; From 7de985ed63505d4b27f114d26874f6f021d6244c Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 15:55:17 -0500 Subject: [PATCH 065/163] use cra pattern for importing react --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- src/FilterLists.Web.V2/src/shared/Description.tsx | 2 +- .../src/shared/buttons/subscribe/SubscribeButton.tsx | 2 +- src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index eea48f5b0..c4d719e76 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,5 +1,5 @@ import { Table } from 'antd'; -import * as React from "react"; +import React from 'react'; import { Description, SubscribeButton, TagCloud } from '../../shared'; import { nameof } from '../../utils'; import './AllListsTable.css'; diff --git a/src/FilterLists.Web.V2/src/shared/Description.tsx b/src/FilterLists.Web.V2/src/shared/Description.tsx index ec7a2d3c4..acd355276 100644 --- a/src/FilterLists.Web.V2/src/shared/Description.tsx +++ b/src/FilterLists.Web.V2/src/shared/Description.tsx @@ -1,4 +1,4 @@ -import * as React from "react"; +import React from 'react'; interface Props { desription: string; diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index fc7afd0ff..fbc0a72ab 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -1,6 +1,6 @@ import { Button, Dropdown, Menu } from 'antd'; import { ButtonProps, ButtonType } from "antd/lib/button"; -import * as React from "react"; +import React from 'react'; import './SubscribeButton.css'; //TODO: import DropdownButtonType from antd rather than redefining if they export the type diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx index 6d38c971d..cf260bae0 100644 --- a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx +++ b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx @@ -1,5 +1,5 @@ import { Tag } from 'antd'; -import * as React from "react"; +import React from 'react'; import styles from './TagCloud.module.css'; interface TagData { From ee5ac67110fe996309ee5dee0749f98e9ddfdd20 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 16:09:44 -0500 Subject: [PATCH 066/163] css updates --- .../{AllListsTable.css => AllListsTable.module.css} | 2 +- .../src/modules/allListsTable/AllListsTable.tsx | 10 ++++++++-- ...{SubscribeButton.css => SubscribeButton.module.css} | 7 +++---- .../src/shared/buttons/subscribe/SubscribeButton.tsx | 6 +++--- .../src/shared/tagCloud/TagCloud.module.css | 1 + 5 files changed, 16 insertions(+), 10 deletions(-) rename src/FilterLists.Web.V2/src/modules/allListsTable/{AllListsTable.css => AllListsTable.module.css} (97%) rename src/FilterLists.Web.V2/src/shared/buttons/subscribe/{SubscribeButton.css => SubscribeButton.module.css} (55%) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css similarity index 97% rename from src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css rename to src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css index 5a637ae03..600fd2ecb 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.css +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css @@ -1,4 +1,4 @@ -td > * { +.nogrow > * { /* limit table cells from wrapping more than 2 lines */ /* https://stackoverflow.com/a/13924997/2343739 */ /* https://stackoverflow.com/a/22042054/2343739 */ diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index c4d719e76..d3475e174 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -2,7 +2,7 @@ import { Table } from 'antd'; import React from 'react'; import { Description, SubscribeButton, TagCloud } from '../../shared'; import { nameof } from '../../utils'; -import './AllListsTable.css'; +import styles from './AllListsTable.module.css'; import { List } from './List'; import { Tag } from './Tag'; @@ -78,30 +78,36 @@ export class AllListsTable extends React.Component<{}, State> { sorter={(a, b) => a.name.localeCompare(b.name)} defaultSortOrder={"ascend"} width={200} + className={styles.nogrow} fixed="left" render={(text: string) =>
{text}
} /> title="Description" dataIndex={nameof("description")} + className={styles.nogrow} render={(text: string, record: List) => } /> title="Software" dataIndex={nameof("syntaxId")} + className={styles.nogrow} render={(text: string) =>
{text}
} /> title="Languages" dataIndex={nameof("languageIds")} + className={styles.nogrow} render={(text: string) =>
{text}
} /> title="Tags" dataIndex={nameof("tagIds")} - width={200} + width={275} + className={styles.nogrow} render={(tagIds: number[]) => tagIds ? tagIds.includes(t.id))} /> : null} /> title="Subscribe" dataIndex={nameof("viewUrl")} width={123} + className={styles.nogrow} fixed={this.state.isNarrowWindow ? undefined : "right"} render={(text: string, record: List, index: number) => } /> diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css similarity index 55% rename from src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css rename to src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css index 3106850cc..185d96c4f 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.css +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css @@ -1,10 +1,9 @@ /* fix font color on dropdown buttons */ -.ant-dropdown-menu-item > a, -.ant-dropdown-menu-submenu-title > a { - color: #fff; +.sub { + color: #fff !important; } /* make non-dropdown button equivalent width to dropdown */ -.ant-btn.single { +.single { width: 106.81px; } diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index fbc0a72ab..f3c6524e3 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -1,7 +1,7 @@ import { Button, Dropdown, Menu } from 'antd'; import { ButtonProps, ButtonType } from "antd/lib/button"; import React from 'react'; -import './SubscribeButton.css'; +import styles from './SubscribeButton.module.css'; //TODO: import DropdownButtonType from antd rather than redefining if they export the type //import { DropdownButtonType } from "antd/lib/dropdown"; @@ -17,7 +17,7 @@ export const SubscribeButton = (props: Props): JSX.Element => (props.viewUrlMirrors && props.viewUrlMirrors.length > 0) ? :
- +
; const SubscribeButtonDropdown = (props: Props): JSX.Element => { @@ -30,7 +30,7 @@ const SubscribeButtonDropdown = (props: Props): JSX.Element => { {props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - + )} }> diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css index 42f8db99a..3bee840b6 100644 --- a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css +++ b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css @@ -1,3 +1,4 @@ +/* allow for 2nd row's tags' bottom border to not be chopped in AllListsTable */ .grow { max-height: none !important; } From 149524e12f0211504a764434415e4ddd5079d5fc Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Wed, 7 Aug 2019 17:37:34 -0500 Subject: [PATCH 067/163] tweak auto-pageSize math --- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index d3475e174..476ecbfc6 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -50,7 +50,7 @@ export class AllListsTable extends React.Component<{}, State> { } private updatePageSize() { - const pageSize = Math.floor((window.innerHeight - 275.5) / 59); + const pageSize = Math.floor((window.innerHeight - 275.5) / 72); this.setState({ pageSize: pageSize, pageSizeOptions: [5, 10, 20, 500, 2000, pageSize].sort((a, b) => a - b).map(String), From a4714ce1b6c756b0009c010228cf22d17b8761c8 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Fri, 16 Aug 2019 15:06:20 -0500 Subject: [PATCH 068/163] update react-scripts --- src/FilterLists.Web.V2/package-lock.json | Bin 541902 -> 564019 bytes src/FilterLists.Web.V2/package.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index e0870e3995c5362c48ab202aa61b9c1aa346d724..b28dbeade61363ca74237e98d8002f5fc28f8587 100644 GIT binary patch delta 33430 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�P?V~K1z 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 Date: Fri, 16 Aug 2019 15:48:10 -0500 Subject: [PATCH 069/163] port sort by tags --- .../src/modules/allListsTable/AllListsTable.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 476ecbfc6..575286f12 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,5 +1,6 @@ import { Table } from 'antd'; import React from 'react'; + import { Description, SubscribeButton, TagCloud } from '../../shared'; import { nameof } from '../../utils'; import styles from './AllListsTable.module.css'; @@ -58,6 +59,20 @@ export class AllListsTable extends React.Component<{}, State> { }); } + private tagSorter = (a: number[], b: number[], tags: Tag[]): number => { + return a + ? b + ? a.length === b.length + ? tags.filter((t: Tag) => a.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() > tags.filter((t: Tag) => b.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() + ? 1 + : -1 + : a.length > b.length + ? -1 + : 1 + : -1 + : 1; + }; + render() { return ( @@ -100,6 +115,7 @@ export class AllListsTable extends React.Component<{}, State> { title="Tags" dataIndex={nameof("tagIds")} + sorter={(a, b) => this.tagSorter(a.tagIds, b.tagIds, this.state.tags)} width={275} className={styles.nogrow} render={(tagIds: number[]) => From 3f0dd3a0d1b9e22187f8c6c60d478162f91ee46d Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Fri, 16 Aug 2019 16:13:30 -0500 Subject: [PATCH 070/163] rm some whitespace to fit more rows per page --- src/FilterLists.Web.V2/src/App.tsx | 3 ++- .../src/modules/allListsTable/AllListsTable.module.css | 8 +++++++- .../src/modules/allListsTable/AllListsTable.tsx | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 08ecc254f..7dd6ac1e9 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,5 +1,6 @@ import { Layout, Menu } from 'antd'; import React from 'react'; + import { AllListsTable } from './modules'; const { Header, Content, Footer } = Layout; @@ -16,7 +17,7 @@ const App: React.FC = () => { /> -
+
diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css index 600fd2ecb..11d17859b 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css @@ -4,7 +4,7 @@ /* https://stackoverflow.com/a/22042054/2343739 */ overflow: hidden; text-overflow: ellipsis; - display: -webkit-box !important; /* TODO: refactor out important */ + display: -webkit-box !important; -webkit-box-orient: vertical; -webkit-line-clamp: 2; /* number of lines to show */ line-height: 1.5; /* fallback */ @@ -13,3 +13,9 @@ /* fixed row height */ min-height: 3em; } + +.nogrow { + /* eliminate top and bottom padding in cells to fit more rows per page */ + padding-top: 0px !important; + padding-bottom: 0px !important; +} diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 575286f12..d345f851a 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -51,7 +51,7 @@ export class AllListsTable extends React.Component<{}, State> { } private updatePageSize() { - const pageSize = Math.floor((window.innerHeight - 275.5) / 72); + const pageSize = Math.floor((window.innerHeight - 211.5) / 56); this.setState({ pageSize: pageSize, pageSizeOptions: [5, 10, 20, 500, 2000, pageSize].sort((a, b) => a - b).map(String), From d3f8752e771a3709d7b0b081608c8c48c893c9b4 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 09:06:55 -0500 Subject: [PATCH 071/163] auto-determine copyright year --- src/FilterLists.Web.V2/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 7dd6ac1e9..a7c401e10 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -21,7 +21,7 @@ const App: React.FC = () => {
-
©2019 Collin M. Barrett
+
©{(new Date()).getFullYear()} Collin M. Barrett
); } From ceb4aaa40df7515044b8d73c7cde6a2d58f42a83 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 09:26:40 -0500 Subject: [PATCH 072/163] add logo --- src/FilterLists.Web.V2/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index a7c401e10..f343001da 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -9,7 +9,7 @@ const App: React.FC = () => { return (
-
+ FilterLists logo Date: Sat, 24 Aug 2019 09:50:27 -0500 Subject: [PATCH 073/163] add footer links --- src/FilterLists.Web.V2/src/App.tsx | 55 ++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index f343001da..067710e56 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -9,21 +9,62 @@ const App: React.FC = () => { return (
- FilterLists logo - + +
-
©{(new Date()).getFullYear()} Collin M. Barrett
+
+ | | | | +
); } +const Logo = () => + FilterLists logo; + +const CopyrightAuthor = () => + + ©{new Date().getFullYear()}  +
+ Collin M. Barrett + ; + +const Community = () => + + Community + ; + +const GitHub = () => + + GitHub + ; + +const Api = () => + + API + ; + +const Donate = () => + + Donate + ; + export default App; \ No newline at end of file From 22d9bf3cb781b7b882041dceba45c49bccc2e67d Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 10:01:54 -0500 Subject: [PATCH 074/163] Description should never return null --- src/FilterLists.Web.V2/src/shared/Description.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/shared/Description.tsx b/src/FilterLists.Web.V2/src/shared/Description.tsx index acd355276..4b030b5f0 100644 --- a/src/FilterLists.Web.V2/src/shared/Description.tsx +++ b/src/FilterLists.Web.V2/src/shared/Description.tsx @@ -5,7 +5,7 @@ interface Props { desriptionSourceUrl: string; }; -export const Description = (props: Props): JSX.Element | null => +export const Description = (props: Props): JSX.Element => props.desriptionSourceUrl ?
{props.desription}
:

{props.desription}

; \ No newline at end of file From 089da5e7b8535b299d18d0440062e41aa74a464a Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 10:02:19 -0500 Subject: [PATCH 075/163] check if tag array has length in TagCloud --- src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx index cf260bae0..80b71d07a 100644 --- a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx +++ b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx @@ -12,7 +12,7 @@ interface Props { }; export const TagCloud = (props: Props): JSX.Element | null => { - return props.tags + return props.tags && props.tags.length ?
{props.tags.map((t: TagData, i: number) => {t.name})} From 833ddae587aa9d33645079644923a8e19f517988 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 11:30:31 -0500 Subject: [PATCH 076/163] tidy SubscribeButton --- .../buttons/subscribe/SubscribeButton.tsx | 83 +++++++++---------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index f3c6524e3..62f092bbd 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -14,30 +14,37 @@ interface Props { }; export const SubscribeButton = (props: Props): JSX.Element => - (props.viewUrlMirrors && props.viewUrlMirrors.length > 0) - ? + (props.viewUrlMirrors && props.viewUrlMirrors.length) + ? :
; -const SubscribeButtonDropdown = (props: Props): JSX.Element => { +const ButtonDropdown = (props: Props): JSX.Element => { var buttonProps = buildButtonProps(props.name, props.viewUrl); //TODO: pass title (ref https://github.com/ant-design/ant-design/issues/18122) return - {props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - - - )} -
- }> + overlay={}> Subscribe ; }; +interface DropdownOverlayProps { + name: string; + viewUrlMirrors: string[]; +}; + +const DropdownOverlay = (props: DropdownOverlayProps) => + + {props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => + + + + )} + ; + const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { let type: ButtonType = "primary"; @@ -45,38 +52,30 @@ const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { const hrefTitle = `${encodeURIComponent(name)}`; let href = `abp:subscribe?location=${hrefLocation}&title=${hrefTitle}`; - const defaultTitle = (prefix?: string) => `${prefix || ""}Subscribe to ${name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; - let title: string; + let prefixes: string[] = []; + let message = `Subscribe to ${name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; - switch (true) { - - // HTTP protocols - case viewUrl.includes(".onion/"): - type = "dashed"; - title = defaultTitle("Tor address - "); - break; - case viewUrl.includes("http://"): - type = "danger"; - title = defaultTitle("Not Secure - "); - break; - - // Software protocols - case viewUrl.includes(".tpl"): - href = `javascript:window.external.msAddTrackingProtectionList('${hrefLocation}', '${hrefTitle}')`; - title = `Subscribe to ${name} with Internet Explorer's Tracking Protection List feature.`; - break; - case viewUrl.includes(".lsrules"): - href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; - title = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; - break; - case viewUrl.includes("?hostformat=littlesnitch"): - href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; - title = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; - break; - default: - title = defaultTitle(); - break; + // HTTP protocols + if (viewUrl.includes(".onion/")) { + type = "dashed"; + prefixes.push("Tor"); + } + if (viewUrl.includes("http://")) { + type = "danger"; + prefixes.push("Insecure"); } - return { type, href, title } as ButtonProps + // Software protocols + if (viewUrl.includes(".tpl")) { + href = `javascript:window.external.msAddTrackingProtectionList('${hrefLocation}', '${hrefTitle}')`; + message = `Subscribe to ${name} with Internet Explorer's Tracking Protection List feature.`; + } + if (viewUrl.includes(".lsrules") || viewUrl.includes("?hostformat=littlesnitch")) { + href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; + message = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; + } + + const title = `${prefixes.length ? prefixes.join(" | ") : ""}${message}`; + + return { type, href, title } } From 867277716c70586fd0187c96c3202d2c32487968 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 11:33:39 -0500 Subject: [PATCH 077/163] fix subscribe button title prefixes --- .../src/shared/buttons/subscribe/SubscribeButton.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index 62f092bbd..a7f9a8594 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -58,11 +58,11 @@ const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { // HTTP protocols if (viewUrl.includes(".onion/")) { type = "dashed"; - prefixes.push("Tor"); + prefixes.push("TOR"); } if (viewUrl.includes("http://")) { type = "danger"; - prefixes.push("Insecure"); + prefixes.push("INSECURE"); } // Software protocols @@ -75,7 +75,7 @@ const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { message = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; } - const title = `${prefixes.length ? prefixes.join(" | ") : ""}${message}`; + const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`; return { type, href, title } } From 1747f9888d3eb4d8a341a2baa121dd7481cf7314 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 11:53:29 -0500 Subject: [PATCH 078/163] cleanup some Subscribe button css --- .../buttons/subscribe/SubscribeButton.module.css | 11 ++++++++--- .../src/shared/buttons/subscribe/SubscribeButton.tsx | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css index 185d96c4f..8cea8c069 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css @@ -1,9 +1,14 @@ -/* fix font color on dropdown buttons */ -.sub { +.sub_li { + /* reduce vertical white space around dropdown items */ + height: 24px !important; +} + +.sub_a { + /* fix font color on dropdown buttons */ color: #fff !important; } -/* make non-dropdown button equivalent width to dropdown */ .single { + /* make non-dropdown button equivalent width to dropdown */ width: 106.81px; } diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index a7f9a8594..d5dcf45d1 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -24,6 +24,7 @@ const ButtonDropdown = (props: Props): JSX.Element => { var buttonProps = buildButtonProps(props.name, props.viewUrl); //TODO: pass title (ref https://github.com/ant-design/ant-design/issues/18122) return }> @@ -39,8 +40,8 @@ interface DropdownOverlayProps { const DropdownOverlay = (props: DropdownOverlayProps) => {props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - - + + )} ; From a3edf4bf31b4093d709ec6199ea4693f6aba7e0c Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 11:56:02 -0500 Subject: [PATCH 079/163] udpate npms --- src/FilterLists.Web.V2/package-lock.json | Bin 564019 -> 557772 bytes src/FilterLists.Web.V2/package.json | 18 +++++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index b28dbeade61363ca74237e98d8002f5fc28f8587..6105aad3b263092c1dec64a119a368c21c84bf12 100644 GIT binary patch delta 6901 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 delta 8877 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 z Date: Sat, 24 Aug 2019 11:57:34 -0500 Subject: [PATCH 080/163] pass title to Subscribe button https://github.com/ant-design/ant-design/pull/18130 --- .../src/shared/buttons/subscribe/SubscribeButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index d5dcf45d1..a1579964c 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -22,11 +22,11 @@ export const SubscribeButton = (props: Props): JSX.Element => const ButtonDropdown = (props: Props): JSX.Element => { var buttonProps = buildButtonProps(props.name, props.viewUrl); - //TODO: pass title (ref https://github.com/ant-design/ant-design/issues/18122) return }> Subscribe ; From b46f001d43e864e52f5c062756b7b404f521e1f7 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 12:27:07 -0500 Subject: [PATCH 081/163] re-org methods --- .../modules/allListsTable/AllListsTable.tsx | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index d345f851a..13eb2591c 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -34,10 +34,6 @@ export class AllListsTable extends React.Component<{}, State> { window.addEventListener('resize', this.updatePageSize); } - componentWillUnmount() { - window.removeEventListener('resize', this.updatePageSize); - } - private fetchData() { fetch("/api/v1/lists") .then(response => response.json()) @@ -59,26 +55,12 @@ export class AllListsTable extends React.Component<{}, State> { }); } - private tagSorter = (a: number[], b: number[], tags: Tag[]): number => { - return a - ? b - ? a.length === b.length - ? tags.filter((t: Tag) => a.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() > tags.filter((t: Tag) => b.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() - ? 1 - : -1 - : a.length > b.length - ? -1 - : 1 - : -1 - : 1; - }; - render() { return ( dataSource={this.state.lists} rowKey={record => record.id.toString()} - loading={this.state.lists.length === 0 ? true : false} + loading={this.state.lists.length ? false : true} size="small" pagination={{ size: "small", @@ -130,4 +112,22 @@ export class AllListsTable extends React.Component<{}, State> { ); } + + private tagSorter = (a: number[], b: number[], tags: Tag[]): number => { + return a + ? b + ? a.length === b.length + ? tags.filter((t: Tag) => a.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() > tags.filter((t: Tag) => b.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() + ? 1 + : -1 + : a.length > b.length + ? -1 + : 1 + : -1 + : 1; + }; + + componentWillUnmount() { + window.removeEventListener('resize', this.updatePageSize); + } } \ No newline at end of file From 5bcf367af6879d8d07f1751de8c22a318aba3466 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 12:33:20 -0500 Subject: [PATCH 082/163] add array length check in tagSorter --- .../src/modules/allListsTable/AllListsTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 13eb2591c..3e03ff4f3 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -114,8 +114,8 @@ export class AllListsTable extends React.Component<{}, State> { } private tagSorter = (a: number[], b: number[], tags: Tag[]): number => { - return a - ? b + return a && a.length + ? b && b.length ? a.length === b.length ? tags.filter((t: Tag) => a.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() > tags.filter((t: Tag) => b.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() ? 1 From ef9769741fe204ae9855f1a1cbd2d2e2d639d2fe Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 13:00:18 -0500 Subject: [PATCH 083/163] disable TPL subscribe buttons since site doesn't support IE --- .../buttons/subscribe/SubscribeButton.tsx | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index a1579964c..43d7b37b2 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -17,16 +17,22 @@ export const SubscribeButton = (props: Props): JSX.Element => (props.viewUrlMirrors && props.viewUrlMirrors.length) ? :
- +
; const ButtonDropdown = (props: Props): JSX.Element => { var buttonProps = buildButtonProps(props.name, props.viewUrl); - return }> Subscribe ; @@ -41,13 +47,18 @@ const DropdownOverlay = (props: DropdownOverlayProps) => {props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - + )} ; -const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { +const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => { let type: ButtonType = "primary"; + let disabled: boolean = false; const hrefLocation = `${encodeURIComponent(viewUrl)}`; const hrefTitle = `${encodeURIComponent(name)}`; @@ -68,8 +79,9 @@ const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { // Software protocols if (viewUrl.includes(".tpl")) { - href = `javascript:window.external.msAddTrackingProtectionList('${hrefLocation}', '${hrefTitle}')`; - message = `Subscribe to ${name} with Internet Explorer's Tracking Protection List feature.`; + disabled = true; // IE not supported by FilterLists + // href = `javascript:window.external.msAddTrackingProtectionList('${hrefLocation}', '${hrefTitle}')`; + // message = `Subscribe to ${name} with Internet Explorer's Tracking Protection List feature.`; } if (viewUrl.includes(".lsrules") || viewUrl.includes("?hostformat=littlesnitch")) { href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; @@ -78,5 +90,5 @@ const buildButtonProps = (name: string, viewUrl: string): ButtonProps => { const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`; - return { type, href, title } + return [{ type, href, title }, disabled] } From cb04a7a7866deaf4e354317f18a79d4a3bbe42e6 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 14:13:43 -0500 Subject: [PATCH 084/163] de-dup building buttonProps --- .../buttons/subscribe/SubscribeButton.tsx | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index 43d7b37b2..23d116a48 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -13,19 +13,21 @@ interface Props { viewUrlMirrors: string[]; }; -export const SubscribeButton = (props: Props): JSX.Element => - (props.viewUrlMirrors && props.viewUrlMirrors.length) +export const SubscribeButton = (props: Props): JSX.Element => { + const buttonProps = buildButtonProps(props.name, props.viewUrl); + return (props.viewUrlMirrors && props.viewUrlMirrors.length) ? :
- -
; +
+}; const ButtonDropdown = (props: Props): JSX.Element => { - var buttonProps = buildButtonProps(props.name, props.viewUrl); + const buttonProps = buildButtonProps(props.name, props.viewUrl); return +const DropdownOverlay = (props: DropdownOverlayProps): JSX.Element => - {props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - - - )} + })} ; const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => { @@ -80,8 +83,6 @@ const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] // Software protocols if (viewUrl.includes(".tpl")) { disabled = true; // IE not supported by FilterLists - // href = `javascript:window.external.msAddTrackingProtectionList('${hrefLocation}', '${hrefTitle}')`; - // message = `Subscribe to ${name} with Internet Explorer's Tracking Protection List feature.`; } if (viewUrl.includes(".lsrules") || viewUrl.includes("?hostformat=littlesnitch")) { href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; From e8854727e98ef0fcb62a11a0f785660d0bcfbe9c Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 14:39:00 -0500 Subject: [PATCH 085/163] misc linting --- src/FilterLists.Web.V2/src/App.test.tsx | 3 +- src/FilterLists.Web.V2/src/App.tsx | 37 ++++++++----------- src/FilterLists.Web.V2/src/index.tsx | 8 ++-- .../modules/allListsTable/AllListsTable.tsx | 5 +-- .../src/modules/allListsTable/index.ts | 2 +- src/FilterLists.Web.V2/src/modules/index.ts | 2 +- .../buttons/subscribe/SubscribeButton.tsx | 3 +- .../src/shared/tagCloud/TagCloud.tsx | 3 +- src/FilterLists.Web.V2/src/utils/index.ts | 2 +- 9 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.test.tsx b/src/FilterLists.Web.V2/src/App.test.tsx index a754b201b..7ca229b98 100644 --- a/src/FilterLists.Web.V2/src/App.test.tsx +++ b/src/FilterLists.Web.V2/src/App.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import App from './App'; + +import { App } from './App'; it('renders without crashing', () => { const div = document.createElement('div'); diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 067710e56..c7dfcc82a 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -5,24 +5,21 @@ import { AllListsTable } from './modules'; const { Header, Content, Footer } = Layout; -const App: React.FC = () => { - return ( - -
- - -
- -
- -
-
-
- | | | | -
-
- ); -} +export const App: React.FC = () => + +
+ + +
+ +
+ +
+
+
+ | | | | +
+
; const Logo = () => title="Donate to FilterLists with Beerpay" target="_blank" rel="noopener noreferrer"> Donate - ; - -export default App; \ No newline at end of file + ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/index.tsx b/src/FilterLists.Web.V2/src/index.tsx index c9a1418bf..8fec59ed5 100644 --- a/src/FilterLists.Web.V2/src/index.tsx +++ b/src/FilterLists.Web.V2/src/index.tsx @@ -1,6 +1,8 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; import './index.css'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { App } from './App'; + ReactDOM.render(, document.getElementById('root')); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 3e03ff4f3..65fa396cf 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -113,8 +113,8 @@ export class AllListsTable extends React.Component<{}, State> { ); } - private tagSorter = (a: number[], b: number[], tags: Tag[]): number => { - return a && a.length + private tagSorter = (a: number[], b: number[], tags: Tag[]): number => + a && a.length ? b && b.length ? a.length === b.length ? tags.filter((t: Tag) => a.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() > tags.filter((t: Tag) => b.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() @@ -125,7 +125,6 @@ export class AllListsTable extends React.Component<{}, State> { : 1 : -1 : 1; - }; componentWillUnmount() { window.removeEventListener('resize', this.updatePageSize); diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/index.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/index.ts index fd3e7fb18..35e7597f6 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/index.ts +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/index.ts @@ -1,3 +1,3 @@ -import { AllListsTable } from './AllListsTable' +import { AllListsTable } from './AllListsTable'; export { AllListsTable } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/modules/index.ts b/src/FilterLists.Web.V2/src/modules/index.ts index 820f33938..5b656626f 100644 --- a/src/FilterLists.Web.V2/src/modules/index.ts +++ b/src/FilterLists.Web.V2/src/modules/index.ts @@ -1,3 +1,3 @@ -import { AllListsTable } from './allListsTable' +import { AllListsTable } from './allListsTable'; export { AllListsTable } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx index 23d116a48..41a587c36 100644 --- a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx @@ -1,6 +1,7 @@ import { Button, Dropdown, Menu } from 'antd'; -import { ButtonProps, ButtonType } from "antd/lib/button"; +import { ButtonProps, ButtonType } from 'antd/lib/button'; import React from 'react'; + import styles from './SubscribeButton.module.css'; //TODO: import DropdownButtonType from antd rather than redefining if they export the type diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx index 80b71d07a..cf45551f7 100644 --- a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx +++ b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx @@ -1,5 +1,6 @@ import { Tag } from 'antd'; import React from 'react'; + import styles from './TagCloud.module.css'; interface TagData { @@ -8,7 +9,7 @@ interface TagData { }; interface Props { - tags?: TagData[] + tags: TagData[] }; export const TagCloud = (props: Props): JSX.Element | null => { diff --git a/src/FilterLists.Web.V2/src/utils/index.ts b/src/FilterLists.Web.V2/src/utils/index.ts index 47426d11c..61acd744c 100644 --- a/src/FilterLists.Web.V2/src/utils/index.ts +++ b/src/FilterLists.Web.V2/src/utils/index.ts @@ -1,3 +1,3 @@ -import { nameof } from './nameof' +import { nameof } from './nameof'; export { nameof } \ No newline at end of file From 5e66006aada7a8ec2899da2588697402819f21a9 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 15:10:40 -0500 Subject: [PATCH 086/163] tag-ify Languages column --- .../modules/allListsTable/AllListsTable.tsx | 51 ++++++++++++------- .../src/modules/allListsTable/Language.ts | 6 +++ src/FilterLists.Web.V2/src/shared/index.ts | 3 +- .../languageCloud/LanguageCloud.module.css | 4 ++ .../shared/languageCloud/LanguageCloud.tsx | 21 ++++++++ .../src/shared/languageCloud/index.ts | 3 ++ .../src/shared/tagCloud/TagCloud.tsx | 7 ++- 7 files changed, 73 insertions(+), 22 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/modules/allListsTable/Language.ts create mode 100644 src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.module.css create mode 100644 src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.tsx create mode 100644 src/FilterLists.Web.V2/src/shared/languageCloud/index.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 65fa396cf..767983bb3 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -1,14 +1,16 @@ import { Table } from 'antd'; import React from 'react'; -import { Description, SubscribeButton, TagCloud } from '../../shared'; +import { Description, LanguageCloud, SubscribeButton, TagCloud } from '../../shared'; import { nameof } from '../../utils'; import styles from './AllListsTable.module.css'; +import { Language } from './Language'; import { List } from './List'; import { Tag } from './Tag'; interface State { lists: List[]; + languages: Language[]; tags: Tag[]; pageSize: number; pageSizeOptions: string[]; @@ -20,6 +22,7 @@ export class AllListsTable extends React.Component<{}, State> { super(props); this.state = { lists: [], + languages: [], tags: [], pageSize: 0, pageSizeOptions: [], @@ -40,6 +43,11 @@ export class AllListsTable extends React.Component<{}, State> { .then(json => (json as List[]).sort((a, b) => a.name.localeCompare(b.name))) .then(lists => { this.setState({ lists: lists }); }) + fetch("/api/v1/languages") + .then(response => response.json()) + .then(json => (json as Language[]).sort((a, b) => a.name.localeCompare(b.name))) + .then(languages => { this.setState({ languages: languages }); }) + fetch("/api/v1/tags") .then(response => response.json()) .then(json => (json as Tag[]).sort((a, b) => a.name.localeCompare(b.name))) @@ -92,12 +100,15 @@ export class AllListsTable extends React.Component<{}, State> { title="Languages" dataIndex={nameof("languageIds")} + sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, this.state.languages)} + width={125} className={styles.nogrow} - render={(text: string) =>
{text}
} /> + render={(languageIds: number[]) => + languageIds ? languageIds.includes(l.id))} /> : null} /> title="Tags" dataIndex={nameof("tagIds")} - sorter={(a, b) => this.tagSorter(a.tagIds, b.tagIds, this.state.tags)} + sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, this.state.tags)} width={275} className={styles.nogrow} render={(tagIds: number[]) => @@ -113,20 +124,26 @@ export class AllListsTable extends React.Component<{}, State> { ); } - private tagSorter = (a: number[], b: number[], tags: Tag[]): number => - a && a.length - ? b && b.length - ? a.length === b.length - ? tags.filter((t: Tag) => a.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() > tags.filter((t: Tag) => b.indexOf(t.id) > -1).map((t: Tag) => t.name).join().toLowerCase() - ? 1 - : -1 - : a.length > b.length - ? -1 - : 1 - : -1 - : 1; - componentWillUnmount() { window.removeEventListener('resize', this.updatePageSize); } -} \ No newline at end of file +} + +interface ArraySortableEntity { + id: number; + name: string; +} + +const arraySorter = (a: number[], b: number[], entities: ArraySortableEntity[]): number => + a && a.length + ? b && b.length + ? a.length === b.length + ? entities.filter((e: ArraySortableEntity) => a.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() + > entities.filter((e: ArraySortableEntity) => b.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() + ? 1 + : -1 + : a.length > b.length + ? -1 + : 1 + : -1 + : 1; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/Language.ts b/src/FilterLists.Web.V2/src/modules/allListsTable/Language.ts new file mode 100644 index 000000000..c453f42a6 --- /dev/null +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/Language.ts @@ -0,0 +1,6 @@ +export interface Language { + id: number; + filterListIds: number[]; + iso6391: string; + name: string; +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/index.ts b/src/FilterLists.Web.V2/src/shared/index.ts index 7ed61c7b7..ee6d73771 100644 --- a/src/FilterLists.Web.V2/src/shared/index.ts +++ b/src/FilterLists.Web.V2/src/shared/index.ts @@ -1,5 +1,6 @@ import { SubscribeButton } from './buttons'; import { Description } from './Description'; +import { LanguageCloud } from './languageCloud'; import { TagCloud } from './tagCloud'; -export { SubscribeButton, Description, TagCloud }; +export { SubscribeButton, Description, LanguageCloud, TagCloud }; diff --git a/src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.module.css b/src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.module.css new file mode 100644 index 000000000..3bee840b6 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.module.css @@ -0,0 +1,4 @@ +/* allow for 2nd row's tags' bottom border to not be chopped in AllListsTable */ +.grow { + max-height: none !important; +} diff --git a/src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.tsx b/src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.tsx new file mode 100644 index 000000000..44c474942 --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.tsx @@ -0,0 +1,21 @@ +import { Tag } from 'antd'; +import React from 'react'; + +import styles from './LanguageCloud.module.css'; + +interface LanguageData { + iso6391: string; + name: string; +}; + +interface Props { + languages: LanguageData[] +}; + +export const LanguageCloud = (props: Props): JSX.Element | null => + props.languages && props.languages.length + ?
+ {props.languages.map((l: LanguageData, i: number) => + {l.iso6391})} +
+ : null; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/languageCloud/index.ts b/src/FilterLists.Web.V2/src/shared/languageCloud/index.ts new file mode 100644 index 000000000..063a12c8e --- /dev/null +++ b/src/FilterLists.Web.V2/src/shared/languageCloud/index.ts @@ -0,0 +1,3 @@ +import { LanguageCloud } from './LanguageCloud'; + +export { LanguageCloud }; diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx index cf45551f7..9c93523c7 100644 --- a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx +++ b/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx @@ -12,11 +12,10 @@ interface Props { tags: TagData[] }; -export const TagCloud = (props: Props): JSX.Element | null => { - return props.tags && props.tags.length +export const TagCloud = (props: Props): JSX.Element | null => + props.tags && props.tags.length ?
{props.tags.map((t: TagData, i: number) => {t.name})}
- : null; -}; \ No newline at end of file + : null; \ No newline at end of file From 0bb7a8eb5f245beb8dc9fac3cd4933e021e1e8ac Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 15:35:44 -0500 Subject: [PATCH 087/163] explicitly define return types --- src/FilterLists.Web.V2/src/App.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index c7dfcc82a..d41e9f416 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -21,13 +21,13 @@ export const App: React.FC = () => ; -const Logo = () => +const Logo = (): JSX.Element => FilterLists logo; -const CopyrightAuthor = () => +const CopyrightAuthor = (): JSX.Element => ©{new Date().getFullYear()}  Collin M. Barrett ; -const Community = () => +const Community = (): JSX.Element => Community ; -const GitHub = () => +const GitHub = (): JSX.Element => GitHub ; -const Api = () => +const Api = (): JSX.Element => API ; -const Donate = () => +const Donate = (): JSX.Element => From f68b0e9211dcfa94d112f6c32c99b4980b95b620 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 15:42:16 -0500 Subject: [PATCH 088/163] tweak table scroll position --- .../src/modules/allListsTable/AllListsTable.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx index 767983bb3..bbd87ecaa 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx @@ -76,7 +76,7 @@ export class AllListsTable extends React.Component<{}, State> { showSizeChanger: true, pageSizeOptions: this.state.pageSizeOptions }} - scroll={{ x: this.state.isNarrowWindow ? 576 : 1600 }}> + scroll={{ x: this.state.isNarrowWindow ? 576 : 1200 }}> title="Name" dataIndex={nameof("name")} @@ -104,7 +104,9 @@ export class AllListsTable extends React.Component<{}, State> { width={125} className={styles.nogrow} render={(languageIds: number[]) => - languageIds ? languageIds.includes(l.id))} /> : null} /> + languageIds + ? languageIds.includes(l.id))} /> + : null} /> title="Tags" dataIndex={nameof("tagIds")} @@ -112,7 +114,9 @@ export class AllListsTable extends React.Component<{}, State> { width={275} className={styles.nogrow} render={(tagIds: number[]) => - tagIds ? tagIds.includes(t.id))} /> : null} /> + tagIds + ? tagIds.includes(t.id))} /> + : null} /> title="Subscribe" dataIndex={nameof("viewUrl")} width={123} From 6c87ed1be94b3d50082f3161b509d3591eadc11e Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 17:00:45 -0500 Subject: [PATCH 089/163] flatten components, add list details drawer stub --- src/FilterLists.Web.V2/src/App.tsx | 2 +- .../src/components/Description.tsx | 11 ++++++ .../allListsTable/AllListsTable.module.css | 0 .../allListsTable/AllListsTable.tsx | 16 ++++---- .../allListsTable/index.ts | 0 .../{shared => components}/buttons/index.ts | 0 .../subscribe/SubscribeButton.module.css | 0 .../buttons/subscribe/SubscribeButton.tsx | 0 .../buttons/subscribe/index.ts | 0 .../src/components/index.ts | 8 ++++ .../languageCloud/LanguageCloud.module.css | 0 .../languageCloud/LanguageCloud.tsx | 0 .../languageCloud/index.ts | 0 .../components/listDetails/ListDetails.tsx | 39 +++++++++++++++++++ .../src/components/listDetails/index.ts | 3 ++ .../tagCloud/TagCloud.module.css | 0 .../tagCloud/TagCloud.tsx | 0 .../{shared => components}/tagCloud/index.ts | 0 .../allListsTable => interfaces}/Language.ts | 0 .../allListsTable => interfaces}/List.ts | 0 .../allListsTable => interfaces}/Tag.ts | 0 src/FilterLists.Web.V2/src/modules/index.ts | 3 -- .../src/shared/Description.tsx | 11 ------ src/FilterLists.Web.V2/src/shared/index.ts | 6 --- 24 files changed, 69 insertions(+), 30 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/components/Description.tsx rename src/FilterLists.Web.V2/src/{modules => components}/allListsTable/AllListsTable.module.css (100%) rename src/FilterLists.Web.V2/src/{modules => components}/allListsTable/AllListsTable.tsx (89%) rename src/FilterLists.Web.V2/src/{modules => components}/allListsTable/index.ts (100%) rename src/FilterLists.Web.V2/src/{shared => components}/buttons/index.ts (100%) rename src/FilterLists.Web.V2/src/{shared => components}/buttons/subscribe/SubscribeButton.module.css (100%) rename src/FilterLists.Web.V2/src/{shared => components}/buttons/subscribe/SubscribeButton.tsx (100%) rename src/FilterLists.Web.V2/src/{shared => components}/buttons/subscribe/index.ts (100%) create mode 100644 src/FilterLists.Web.V2/src/components/index.ts rename src/FilterLists.Web.V2/src/{shared => components}/languageCloud/LanguageCloud.module.css (100%) rename src/FilterLists.Web.V2/src/{shared => components}/languageCloud/LanguageCloud.tsx (100%) rename src/FilterLists.Web.V2/src/{shared => components}/languageCloud/index.ts (100%) create mode 100644 src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx create mode 100644 src/FilterLists.Web.V2/src/components/listDetails/index.ts rename src/FilterLists.Web.V2/src/{shared => components}/tagCloud/TagCloud.module.css (100%) rename src/FilterLists.Web.V2/src/{shared => components}/tagCloud/TagCloud.tsx (100%) rename src/FilterLists.Web.V2/src/{shared => components}/tagCloud/index.ts (100%) rename src/FilterLists.Web.V2/src/{modules/allListsTable => interfaces}/Language.ts (100%) rename src/FilterLists.Web.V2/src/{modules/allListsTable => interfaces}/List.ts (100%) rename src/FilterLists.Web.V2/src/{modules/allListsTable => interfaces}/Tag.ts (100%) delete mode 100644 src/FilterLists.Web.V2/src/modules/index.ts delete mode 100644 src/FilterLists.Web.V2/src/shared/Description.tsx delete mode 100644 src/FilterLists.Web.V2/src/shared/index.ts diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index d41e9f416..dbd1fff01 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,7 +1,7 @@ import { Layout, Menu } from 'antd'; import React from 'react'; -import { AllListsTable } from './modules'; +import { AllListsTable } from './components'; const { Header, Content, Footer } = Layout; diff --git a/src/FilterLists.Web.V2/src/components/Description.tsx b/src/FilterLists.Web.V2/src/components/Description.tsx new file mode 100644 index 000000000..a2862dbf7 --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/Description.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +interface Props { + description: string; + descriptionSourceUrl: string; +}; + +export const Description = (props: Props): JSX.Element => + props.description + ?
{props.description}
+ :

{props.description}

; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.module.css rename to src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.module.css diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx similarity index 89% rename from src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx rename to src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx index bbd87ecaa..17017b9d6 100644 --- a/src/FilterLists.Web.V2/src/modules/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx @@ -1,12 +1,12 @@ import { Table } from 'antd'; import React from 'react'; -import { Description, LanguageCloud, SubscribeButton, TagCloud } from '../../shared'; +import { Description, LanguageCloud, ListDetails, TagCloud } from '..'; +import { Language } from '../../interfaces/Language'; +import { List } from '../../interfaces/List'; +import { Tag } from '../../interfaces/Tag'; import { nameof } from '../../utils'; import styles from './AllListsTable.module.css'; -import { Language } from './Language'; -import { List } from './List'; -import { Tag } from './Tag'; interface State { lists: List[]; @@ -90,8 +90,7 @@ export class AllListsTable extends React.Component<{}, State> { title="Description" dataIndex={nameof("description")} className={styles.nogrow} - render={(text: string, record: List) => - } /> + render={(_text: string, record: List) => } /> title="Software" dataIndex={nameof("syntaxId")} @@ -117,13 +116,12 @@ export class AllListsTable extends React.Component<{}, State> { tagIds ? tagIds.includes(t.id))} /> : null} /> - title="Subscribe" + title="Details" dataIndex={nameof("viewUrl")} width={123} className={styles.nogrow} fixed={this.state.isNarrowWindow ? undefined : "right"} - render={(text: string, record: List, index: number) => - } /> + render={(_text: string, record: List) => } /> ); } diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/index.ts b/src/FilterLists.Web.V2/src/components/allListsTable/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/modules/allListsTable/index.ts rename to src/FilterLists.Web.V2/src/components/allListsTable/index.ts diff --git a/src/FilterLists.Web.V2/src/shared/buttons/index.ts b/src/FilterLists.Web.V2/src/components/buttons/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/shared/buttons/index.ts rename to src/FilterLists.Web.V2/src/components/buttons/index.ts diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css b/src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.module.css rename to src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.module.css diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/shared/buttons/subscribe/SubscribeButton.tsx rename to src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.tsx diff --git a/src/FilterLists.Web.V2/src/shared/buttons/subscribe/index.ts b/src/FilterLists.Web.V2/src/components/buttons/subscribe/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/shared/buttons/subscribe/index.ts rename to src/FilterLists.Web.V2/src/components/buttons/subscribe/index.ts diff --git a/src/FilterLists.Web.V2/src/components/index.ts b/src/FilterLists.Web.V2/src/components/index.ts new file mode 100644 index 000000000..a14e1b807 --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/index.ts @@ -0,0 +1,8 @@ +import { AllListsTable } from './allListsTable'; +import { SubscribeButton } from './buttons'; +import { Description } from './Description'; +import { LanguageCloud } from './languageCloud'; +import { ListDetails } from './listDetails'; +import { TagCloud } from './tagCloud'; + +export { SubscribeButton, Description, LanguageCloud, TagCloud, AllListsTable, ListDetails }; diff --git a/src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.module.css b/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.module.css rename to src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.module.css diff --git a/src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.tsx b/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/shared/languageCloud/LanguageCloud.tsx rename to src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx diff --git a/src/FilterLists.Web.V2/src/shared/languageCloud/index.ts b/src/FilterLists.Web.V2/src/components/languageCloud/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/shared/languageCloud/index.ts rename to src/FilterLists.Web.V2/src/components/languageCloud/index.ts diff --git a/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx b/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx new file mode 100644 index 000000000..9f1f7d79d --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx @@ -0,0 +1,39 @@ +import { Button, Drawer } from 'antd'; +import React from 'react'; + +import { Description } from '..'; +import { List } from '../../interfaces/List'; + +interface State { + visible: boolean; +} + +interface Props { + list: List; +}; + +export class ListDetails extends React.Component { + constructor(props: any) { + super(props); + this.state = { + visible: false + }; + } + + render() { + return ( + + + this.setState({ visible: false, })}> + + + + ) + } +} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listDetails/index.ts b/src/FilterLists.Web.V2/src/components/listDetails/index.ts new file mode 100644 index 000000000..d1f027755 --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/listDetails/index.ts @@ -0,0 +1,3 @@ +import { ListDetails } from './ListDetails'; + +export { ListDetails }; diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css b/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.module.css rename to src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.module.css diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx b/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/shared/tagCloud/TagCloud.tsx rename to src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx diff --git a/src/FilterLists.Web.V2/src/shared/tagCloud/index.ts b/src/FilterLists.Web.V2/src/components/tagCloud/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/shared/tagCloud/index.ts rename to src/FilterLists.Web.V2/src/components/tagCloud/index.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/Language.ts b/src/FilterLists.Web.V2/src/interfaces/Language.ts similarity index 100% rename from src/FilterLists.Web.V2/src/modules/allListsTable/Language.ts rename to src/FilterLists.Web.V2/src/interfaces/Language.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/List.ts b/src/FilterLists.Web.V2/src/interfaces/List.ts similarity index 100% rename from src/FilterLists.Web.V2/src/modules/allListsTable/List.ts rename to src/FilterLists.Web.V2/src/interfaces/List.ts diff --git a/src/FilterLists.Web.V2/src/modules/allListsTable/Tag.ts b/src/FilterLists.Web.V2/src/interfaces/Tag.ts similarity index 100% rename from src/FilterLists.Web.V2/src/modules/allListsTable/Tag.ts rename to src/FilterLists.Web.V2/src/interfaces/Tag.ts diff --git a/src/FilterLists.Web.V2/src/modules/index.ts b/src/FilterLists.Web.V2/src/modules/index.ts deleted file mode 100644 index 5b656626f..000000000 --- a/src/FilterLists.Web.V2/src/modules/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { AllListsTable } from './allListsTable'; - -export { AllListsTable } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/Description.tsx b/src/FilterLists.Web.V2/src/shared/Description.tsx deleted file mode 100644 index 4b030b5f0..000000000 --- a/src/FilterLists.Web.V2/src/shared/Description.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -interface Props { - desription: string; - desriptionSourceUrl: string; -}; - -export const Description = (props: Props): JSX.Element => - props.desriptionSourceUrl - ?
{props.desription}
- :

{props.desription}

; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/shared/index.ts b/src/FilterLists.Web.V2/src/shared/index.ts deleted file mode 100644 index ee6d73771..000000000 --- a/src/FilterLists.Web.V2/src/shared/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { SubscribeButton } from './buttons'; -import { Description } from './Description'; -import { LanguageCloud } from './languageCloud'; -import { TagCloud } from './tagCloud'; - -export { SubscribeButton, Description, LanguageCloud, TagCloud }; From e81fe4fac858facc4d74ad90f430f3b49c111372 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 17:03:24 -0500 Subject: [PATCH 090/163] add subscribe button to details drawer --- .../src/components/listDetails/ListDetails.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx b/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx index 9f1f7d79d..7a1bb5131 100644 --- a/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx +++ b/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { Description } from '..'; import { List } from '../../interfaces/List'; +import { SubscribeButton } from '../buttons'; interface State { visible: boolean; @@ -32,6 +33,7 @@ export class ListDetails extends React.Component { visible={this.state.visible} onClose={() => this.setState({ visible: false, })}> + ) From 73c6dc3ee8a6ccd9f3e01a2ad7fa4eeb241328fe Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 20:18:49 -0500 Subject: [PATCH 091/163] add routing --- src/FilterLists.Web.V2/package-lock.json | Bin 557772 -> 562449 bytes src/FilterLists.Web.V2/package.json | 2 + src/FilterLists.Web.V2/src/App.tsx | 41 +++++++++++------- .../allListsTable/AllListsTable.tsx | 1 - 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index 6105aad3b263092c1dec64a119a368c21c84bf12..1f6d43ece995aaf730ab3f40acbce16fb81f4419 100644 GIT binary patch delta 2365 zcmb7`eT>_78OP-$c5Z8Ry({eQ+Uu#;aJ@luIlm-!6424wd4F}@Uk+)K6WclG&57eU zjzyuJ7~MF53fcBU8iEcX1V~In2p!r#OhQ5eI@SZkkl>$5{55He!GzF60pCk+*D^F= z$&!DME&KcYzTf8~-+sdJOB$#$xKM=7Kpt>2Iz>);f44ufUscAa3q8DY zdDgwpybZ0C>UmNg_0^G)Op~puv+YbY5_~R>1_Z&UwmVrlk{!lEezn}qck=FdDq(bV znTW>d7BOOjDM^fsSOViILf_0LtA;a|6f2z(=v$%r$=%%ruT(0{0=7eBrYlfS65x;O;u1#oyV8p?Wf?67Mnz*A&_-VuX9ea zo$!xzS?feHjb1698a2m5vR$Cj08fd@h@9zr!;jKQT7li3R^;2I1e_QQ>t^xs(kZy=ECp#v!{UIy29EDPWYVzW*D3cDxh-;j&P z)tOIp9uT}&a(Te+47^$t!dx?7r1RBUCfXpFU7V^HDI>dZr0PP z1^H@)5A&kZ$c9CV^q4c?fyL*{AOnYUZN^$XikOaS*ZM4kTcfJ|n0A1y?QV5=EuRz!^L`B_?_x^a>c z>$z4TpH_;J=E1deoQe%b@unnFqjqmIfiVR!T$8;0grBb@^VLng)hFA`py}3%&32Wk zg6Bz_6I}ZeG;PJ#32!w*k06S>{e?Tze?Eg#M6ggQZuXUT6bRBwSBPyUf4$FfOro2 zFu3!mnYQl)tOU5S2E*s-riH5DIxw;>cU3`GO&2>-S8`3#mifuGA6+aGnv)d-H8gHZ zDU~cmQx(%Hnvvren)2iVf>-2J9u=7}l}||t&M4+Xs=J}<P)E(q8{FR?M+B`G@5r_qQZJZdtxTUxIh&OUU}S9~hT!z-9yIZzIV3 z`%a3B1h0S2x>^XOyn|sNlTOs|v|cZ463Gx-4y#!vo6A;&dQva-_(8@KEPFDwTEAKr za#C_!LJKOM=L3pXAe!}Yg|2i;g^r=+4JDJK++a71tW1`t?fc$2Oz#|P4=*1cj>7;s zKECXD%(L!aH(LX5uEDF58}Kany<~B~`&$dXzl|({Ctrh3P47AFQf1SEhM@OA=5fm$ z`1%Mr4L<)%=*+)ZS~}`^E>R;jzy`6nNtNNP&W$Q`sCIzp9pRe0y zAPi*d$m$aAl1!~=q9gkm-WlLDUo|KdI-^R?tNK8H#d_w%Fy$74S%pq5rg3tO>ME=f)*+CII`u&!0tC8C-}+N;D-SD zXJ{7O`Zc@^W?n{+2jQ}h!Xt0bAED=c!E)%a!Ih%7G}(1BO5B%~VmXqd^mIm5_=1*f>HT&v(AIHxmc@sR5Bwl&d(Y$L z5At|#c-KMu=Ami#L3=L=``8`GZB209E4hdX_vC81Mu!c5o5y`QBQElMLtzO4#qtE}!@W4>bk?_WsiGcj zR@iDHOf?I1N-3r{mCz=h(Mp)n-V&P<-@$xRF2fg+nXZh7hq=ZESevn*-Ff1a{nk$* z7r1J-nPUG1*}&yL*xgI_vC5QoUtFKLYr8nPWw*&;cAPAiOU;Or3t+{5#7mV(_n0p8 z6*20ou~azS8E>+~qGAM%gfAF#qw!poAd5k-v*Gc_%PBlr8I3!GL@38NgGLPF3!yB% zvEkUCldA{g;y8jN$Sxpf4@6=uh*&(jVbb%S#(OZG;h+_e*|owYCha$W2vC_8DWB{% z(v_;h2UNV3@s$Tsr0ip5qQ!ae8WBs8@g$nZ1BGz~SIStYh8p={eAvY{i%L+}J%heh z%@g6Wk)bzsPXERpWvnKw!7D}k61XyF4%1&gV<*lWBe*H**a|?~$j2(qdX-OiIoci2 zwG>yVV6ik`2&8=-9~UNuRX?MJ`W<~(?fGg+%wHd%t#T=wDMjkEn-o(mm1hST${%YK Xy`yjwrEoqT4UNn#+eth!b-nW+aVHxi delta 103 zcmV-t0GR)gsv^vVBCrbjll{>cmu@)(7? - -
- - -
- -
- -
-
-
- | | | | -
-
; + + +
+ + +
+ +
+ + + + +
+
+
+ | | | | +
+
+
; const Logo = (): JSX.Element => title="Donate to FilterLists with Beerpay" target="_blank" rel="noopener noreferrer"> Donate -
; \ No newline at end of file + ; + +const NotFound = (props: RouteComponentProps) => +

+ 404 Not Found: {props.location.pathname} +

; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx index 17017b9d6..5e8ef4b0e 100644 --- a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx @@ -118,7 +118,6 @@ export class AllListsTable extends React.Component<{}, State> { : null} /> title="Details" dataIndex={nameof("viewUrl")} - width={123} className={styles.nogrow} fixed={this.state.isNarrowWindow ? undefined : "right"} render={(_text: string, record: List) => } /> From 84b0d0adcc82b05b66280ea1186fc88c86facde8 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 20:20:18 -0500 Subject: [PATCH 092/163] add routing --- src/FilterLists.Web.V2/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 335b8162c..e4c43629a 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -70,7 +70,7 @@ const Donate = (): JSX.Element => Donate ; -const NotFound = (props: RouteComponentProps) => +const NotFound = (props: RouteComponentProps): JSX.Element =>

404 Not Found: {props.location.pathname}

; \ No newline at end of file From 66f6aba742fc25ddd826321bcde8e74cd97ee621 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 20:20:56 -0500 Subject: [PATCH 093/163] re-order components --- src/FilterLists.Web.V2/src/App.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index e4c43629a..dc88bea5d 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -33,6 +33,11 @@ const Logo = (): JSX.Element => height="44px" style={{ background: '#fff' }} />; +const NotFound = (props: RouteComponentProps): JSX.Element => +

+ 404 Not Found: {props.location.pathname} +

; + const CopyrightAuthor = (): JSX.Element => ©{new Date().getFullYear()}  @@ -68,9 +73,4 @@ const Donate = (): JSX.Element => title="Donate to FilterLists with Beerpay" target="_blank" rel="noopener noreferrer"> Donate - ; - -const NotFound = (props: RouteComponentProps): JSX.Element => -

- 404 Not Found: {props.location.pathname} -

; \ No newline at end of file + ; \ No newline at end of file From 523cd53e95663327d8f2207db7949e599ecda1bf Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 24 Aug 2019 20:55:43 -0500 Subject: [PATCH 094/163] hide some cols on mobile --- .../allListsTable/AllListsTable.tsx | 75 +++++++++++-------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx index 5e8ef4b0e..b09951d91 100644 --- a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx @@ -76,50 +76,59 @@ export class AllListsTable extends React.Component<{}, State> { showSizeChanger: true, pageSizeOptions: this.state.pageSizeOptions }} - scroll={{ x: this.state.isNarrowWindow ? 576 : 1200 }}> + scroll={{ x: this.state.isNarrowWindow ? undefined : 1200 }}> title="Name" dataIndex={nameof("name")} sorter={(a, b) => a.name.localeCompare(b.name)} defaultSortOrder={"ascend"} - width={200} + width={this.state.isNarrowWindow ? undefined : 200} className={styles.nogrow} fixed="left" render={(text: string) =>
{text}
} /> + {this.state.isNarrowWindow + ? null + : + title="Description" + dataIndex={nameof("description")} + className={styles.nogrow} + render={(_text: string, record: List) => } />} + {this.state.isNarrowWindow + ? null + : + title="Software" + dataIndex={nameof("syntaxId")} + className={styles.nogrow} + render={(text: string) =>
{text}
} />} + {this.state.isNarrowWindow + ? null + : + title="Languages" + dataIndex={nameof("languageIds")} + sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, this.state.languages)} + width={125} + className={styles.nogrow} + render={(languageIds: number[]) => + languageIds + ? languageIds.includes(l.id))} /> + : null} />} + {this.state.isNarrowWindow + ? null + : + title="Tags" + dataIndex={nameof("tagIds")} + sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, this.state.tags)} + width={275} + className={styles.nogrow} + render={(tagIds: number[]) => + tagIds + ? tagIds.includes(t.id))} /> + : null} />} - title="Description" - dataIndex={nameof("description")} - className={styles.nogrow} - render={(_text: string, record: List) => } /> - - title="Software" - dataIndex={nameof("syntaxId")} - className={styles.nogrow} - render={(text: string) =>
{text}
} /> - - title="Languages" - dataIndex={nameof("languageIds")} - sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, this.state.languages)} - width={125} - className={styles.nogrow} - render={(languageIds: number[]) => - languageIds - ? languageIds.includes(l.id))} /> - : null} /> - - title="Tags" - dataIndex={nameof("tagIds")} - sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, this.state.tags)} - width={275} - className={styles.nogrow} - render={(tagIds: number[]) => - tagIds - ? tagIds.includes(t.id))} /> - : null} /> - title="Details" + title="Details" dataIndex={nameof("viewUrl")} className={styles.nogrow} - fixed={this.state.isNarrowWindow ? undefined : "right"} + fixed="right" render={(_text: string, record: List) => } /> ); From 0d3e59fd812974cef3d44278c3a0ae95436a7da4 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 07:45:03 -0500 Subject: [PATCH 095/163] limit page size options --- .../src/components/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx index b09951d91..b22b8955d 100644 --- a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx @@ -58,7 +58,7 @@ export class AllListsTable extends React.Component<{}, State> { const pageSize = Math.floor((window.innerHeight - 211.5) / 56); this.setState({ pageSize: pageSize, - pageSizeOptions: [5, 10, 20, 500, 2000, pageSize].sort((a, b) => a - b).map(String), + pageSizeOptions: [200, 2000, pageSize].sort((a, b) => a - b).map(String), isNarrowWindow: window.innerWidth < 576 ? true : false }); } From 6d430168dbd02b2726390711eb01232f237a0717 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 07:45:34 -0500 Subject: [PATCH 096/163] pre-sort page size options --- .../src/components/allListsTable/AllListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx index b22b8955d..36c927aab 100644 --- a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx @@ -58,7 +58,7 @@ export class AllListsTable extends React.Component<{}, State> { const pageSize = Math.floor((window.innerHeight - 211.5) / 56); this.setState({ pageSize: pageSize, - pageSizeOptions: [200, 2000, pageSize].sort((a, b) => a - b).map(String), + pageSizeOptions: [pageSize, 200, 2000].sort((a, b) => a - b).map(String), isNarrowWindow: window.innerWidth < 576 ? true : false }); } From 15ddb5f32d55b5ae1320a1e8e8a63459e2dd746f Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 09:20:50 -0500 Subject: [PATCH 097/163] always load logo correctly no matter the route --- src/FilterLists.Web.V2/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index dc88bea5d..fb2e3d3ed 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -28,7 +28,7 @@ export const App: React.FC = () => ; const Logo = (): JSX.Element => - FilterLists logo; From 70228ee35356aabfa52aeaa604b12b4d5947e384 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 17:08:31 -0500 Subject: [PATCH 098/163] get routing to list details working, misc. component folder cleanup --- src/FilterLists.Web.V2/src/App.tsx | 10 +- .../src/components/ListDetailsButton.tsx | 16 ++ .../src/components/ListDetailsDrawer.tsx | 19 ++ .../allListsTable/AllListsTable.tsx | 159 ---------------- .../src/components/allListsTable/index.ts | 3 - .../src/components/buttons/index.ts | 3 - .../src/components/index.ts | 9 +- .../components/listDetails/ListDetails.tsx | 41 ----- .../src/components/listDetails/index.ts | 3 - .../ListsTable.module.css} | 0 .../src/components/listsTable/ListsTable.tsx | 172 ++++++++++++++++++ .../src/components/listsTable/index.ts | 3 + .../SubscribeButton.module.css | 0 .../SubscribeButton.tsx | 0 .../subscribe => subscribeButton}/index.ts | 0 15 files changed, 217 insertions(+), 221 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx create mode 100644 src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx delete mode 100644 src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx delete mode 100644 src/FilterLists.Web.V2/src/components/allListsTable/index.ts delete mode 100644 src/FilterLists.Web.V2/src/components/buttons/index.ts delete mode 100644 src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx delete mode 100644 src/FilterLists.Web.V2/src/components/listDetails/index.ts rename src/FilterLists.Web.V2/src/components/{allListsTable/AllListsTable.module.css => listsTable/ListsTable.module.css} (100%) create mode 100644 src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx create mode 100644 src/FilterLists.Web.V2/src/components/listsTable/index.ts rename src/FilterLists.Web.V2/src/components/{buttons/subscribe => subscribeButton}/SubscribeButton.module.css (100%) rename src/FilterLists.Web.V2/src/components/{buttons/subscribe => subscribeButton}/SubscribeButton.tsx (100%) rename src/FilterLists.Web.V2/src/components/{buttons/subscribe => subscribeButton}/index.ts (100%) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index fb2e3d3ed..73523b53e 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -1,13 +1,13 @@ import { Layout, Menu } from 'antd'; import React from 'react'; -import { BrowserRouter, Route, RouteComponentProps, Switch } from 'react-router-dom'; +import { BrowserRouter as Router, Route, RouteComponentProps, Switch } from 'react-router-dom'; -import { AllListsTable } from './components'; +import { ListsTable } from './components'; const { Header, Content, Footer } = Layout; export const App: React.FC = () => - +
@@ -16,7 +16,7 @@ export const App: React.FC = () =>
- +
@@ -25,7 +25,7 @@ export const App: React.FC = () => | | | | - ; + ; const Logo = (): JSX.Element => + ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx new file mode 100644 index 000000000..92ce66130 --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -0,0 +1,19 @@ +import { Drawer } from 'antd'; +import React from 'react'; +import { RouteComponentProps } from 'react-router-dom'; + +import { List } from '../interfaces/List'; +import { Description } from './Description'; +import { SubscribeButton } from './subscribeButton'; + +interface Props { + list: List; +}; + +export const ListDetailsDrawer = (props: RouteComponentProps & Props) => + props.history.push("/")}> + + + ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx b/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx deleted file mode 100644 index 36c927aab..000000000 --- a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import { Table } from 'antd'; -import React from 'react'; - -import { Description, LanguageCloud, ListDetails, TagCloud } from '..'; -import { Language } from '../../interfaces/Language'; -import { List } from '../../interfaces/List'; -import { Tag } from '../../interfaces/Tag'; -import { nameof } from '../../utils'; -import styles from './AllListsTable.module.css'; - -interface State { - lists: List[]; - languages: Language[]; - tags: Tag[]; - pageSize: number; - pageSizeOptions: string[]; - isNarrowWindow: boolean; -} - -export class AllListsTable extends React.Component<{}, State> { - constructor(props: any) { - super(props); - this.state = { - lists: [], - languages: [], - tags: [], - pageSize: 0, - pageSizeOptions: [], - isNarrowWindow: false - }; - this.updatePageSize = this.updatePageSize.bind(this); - } - - componentDidMount() { - this.fetchData(); - this.updatePageSize(); - window.addEventListener('resize', this.updatePageSize); - } - - private fetchData() { - fetch("/api/v1/lists") - .then(response => response.json()) - .then(json => (json as List[]).sort((a, b) => a.name.localeCompare(b.name))) - .then(lists => { this.setState({ lists: lists }); }) - - fetch("/api/v1/languages") - .then(response => response.json()) - .then(json => (json as Language[]).sort((a, b) => a.name.localeCompare(b.name))) - .then(languages => { this.setState({ languages: languages }); }) - - fetch("/api/v1/tags") - .then(response => response.json()) - .then(json => (json as Tag[]).sort((a, b) => a.name.localeCompare(b.name))) - .then(tags => { this.setState({ tags: tags }); }) - } - - private updatePageSize() { - const pageSize = Math.floor((window.innerHeight - 211.5) / 56); - this.setState({ - pageSize: pageSize, - pageSizeOptions: [pageSize, 200, 2000].sort((a, b) => a - b).map(String), - isNarrowWindow: window.innerWidth < 576 ? true : false - }); - } - - render() { - return ( - - dataSource={this.state.lists} - rowKey={record => record.id.toString()} - loading={this.state.lists.length ? false : true} - size="small" - pagination={{ - size: "small", - pageSize: this.state.pageSize, - showSizeChanger: true, - pageSizeOptions: this.state.pageSizeOptions - }} - scroll={{ x: this.state.isNarrowWindow ? undefined : 1200 }}> - - title="Name" - dataIndex={nameof("name")} - sorter={(a, b) => a.name.localeCompare(b.name)} - defaultSortOrder={"ascend"} - width={this.state.isNarrowWindow ? undefined : 200} - className={styles.nogrow} - fixed="left" - render={(text: string) =>
{text}
} /> - {this.state.isNarrowWindow - ? null - : - title="Description" - dataIndex={nameof("description")} - className={styles.nogrow} - render={(_text: string, record: List) => } />} - {this.state.isNarrowWindow - ? null - : - title="Software" - dataIndex={nameof("syntaxId")} - className={styles.nogrow} - render={(text: string) =>
{text}
} />} - {this.state.isNarrowWindow - ? null - : - title="Languages" - dataIndex={nameof("languageIds")} - sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, this.state.languages)} - width={125} - className={styles.nogrow} - render={(languageIds: number[]) => - languageIds - ? languageIds.includes(l.id))} /> - : null} />} - {this.state.isNarrowWindow - ? null - : - title="Tags" - dataIndex={nameof("tagIds")} - sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, this.state.tags)} - width={275} - className={styles.nogrow} - render={(tagIds: number[]) => - tagIds - ? tagIds.includes(t.id))} /> - : null} />} - - title="Details" - dataIndex={nameof("viewUrl")} - className={styles.nogrow} - fixed="right" - render={(_text: string, record: List) => } /> - - ); - } - - componentWillUnmount() { - window.removeEventListener('resize', this.updatePageSize); - } -} - -interface ArraySortableEntity { - id: number; - name: string; -} - -const arraySorter = (a: number[], b: number[], entities: ArraySortableEntity[]): number => - a && a.length - ? b && b.length - ? a.length === b.length - ? entities.filter((e: ArraySortableEntity) => a.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() - > entities.filter((e: ArraySortableEntity) => b.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() - ? 1 - : -1 - : a.length > b.length - ? -1 - : 1 - : -1 - : 1; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/index.ts b/src/FilterLists.Web.V2/src/components/allListsTable/index.ts deleted file mode 100644 index 35e7597f6..000000000 --- a/src/FilterLists.Web.V2/src/components/allListsTable/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { AllListsTable } from './AllListsTable'; - -export { AllListsTable } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/buttons/index.ts b/src/FilterLists.Web.V2/src/components/buttons/index.ts deleted file mode 100644 index a551734b5..000000000 --- a/src/FilterLists.Web.V2/src/components/buttons/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { SubscribeButton } from './subscribe'; - -export { SubscribeButton } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/index.ts b/src/FilterLists.Web.V2/src/components/index.ts index a14e1b807..654f34a7d 100644 --- a/src/FilterLists.Web.V2/src/components/index.ts +++ b/src/FilterLists.Web.V2/src/components/index.ts @@ -1,8 +1,3 @@ -import { AllListsTable } from './allListsTable'; -import { SubscribeButton } from './buttons'; -import { Description } from './Description'; -import { LanguageCloud } from './languageCloud'; -import { ListDetails } from './listDetails'; -import { TagCloud } from './tagCloud'; +import { ListsTable } from './listsTable'; -export { SubscribeButton, Description, LanguageCloud, TagCloud, AllListsTable, ListDetails }; +export { ListsTable }; diff --git a/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx b/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx deleted file mode 100644 index 7a1bb5131..000000000 --- a/src/FilterLists.Web.V2/src/components/listDetails/ListDetails.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Button, Drawer } from 'antd'; -import React from 'react'; - -import { Description } from '..'; -import { List } from '../../interfaces/List'; -import { SubscribeButton } from '../buttons'; - -interface State { - visible: boolean; -} - -interface Props { - list: List; -}; - -export class ListDetails extends React.Component { - constructor(props: any) { - super(props); - this.state = { - visible: false - }; - } - - render() { - return ( - - - this.setState({ visible: false, })}> - - - - - ) - } -} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listDetails/index.ts b/src/FilterLists.Web.V2/src/components/listDetails/index.ts deleted file mode 100644 index d1f027755..000000000 --- a/src/FilterLists.Web.V2/src/components/listDetails/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ListDetails } from './ListDetails'; - -export { ListDetails }; diff --git a/src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.module.css b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/components/allListsTable/AllListsTable.module.css rename to src/FilterLists.Web.V2/src/components/listsTable/ListsTable.module.css diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx new file mode 100644 index 000000000..d55644291 --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -0,0 +1,172 @@ +import { Table } from 'antd'; +import React from 'react'; +import { Route, RouteComponentProps } from 'react-router-dom'; + +import { Language } from '../../interfaces/Language'; +import { List } from '../../interfaces/List'; +import { Tag } from '../../interfaces/Tag'; +import { nameof } from '../../utils'; +import { Description } from '../Description'; +import { LanguageCloud } from '../languageCloud'; +import { ListDetailsButton } from '../ListDetailsButton'; +import { ListDetailsDrawer } from '../ListDetailsDrawer'; +import { TagCloud } from '../tagCloud'; +import styles from './ListsTable.module.css'; + +interface State { + lists: List[]; + languages: Language[]; + tags: Tag[]; + pageSize: number; + pageSizeOptions: string[]; + isNarrowWindow: boolean; +} + +export class ListsTable extends React.Component { + constructor(props: any) { + super(props); + this.state = { + lists: [], + languages: [], + tags: [], + pageSize: 0, + pageSizeOptions: [], + isNarrowWindow: false + }; + this.updatePageSize = this.updatePageSize.bind(this); + } + + componentDidMount() { + this.fetchData(); + this.updatePageSize(); + window.addEventListener('resize', this.updatePageSize); + } + + private fetchData() { + fetch("/api/v1/lists") + .then(response => response.json()) + .then(json => (json as List[]).sort((a, b) => a.name.localeCompare(b.name))) + .then(lists => { this.setState({ lists: lists }); }) + + fetch("/api/v1/languages") + .then(response => response.json()) + .then(json => (json as Language[]).sort((a, b) => a.name.localeCompare(b.name))) + .then(languages => { this.setState({ languages: languages }); }) + + fetch("/api/v1/tags") + .then(response => response.json()) + .then(json => (json as Tag[]).sort((a, b) => a.name.localeCompare(b.name))) + .then(tags => { this.setState({ tags: tags }); }) + } + + private updatePageSize() { + const pageSize = Math.floor((window.innerHeight - 211.5) / 56); + this.setState({ + pageSize: pageSize, + pageSizeOptions: [pageSize, 200, 2000].sort((a, b) => a - b).map(String), + isNarrowWindow: window.innerWidth < 576 ? true : false + }); + } + + render() { + return ( + + + dataSource={this.state.lists} + rowKey={record => record.id.toString()} + loading={this.state.lists.length ? false : true} + size="small" + pagination={{ + size: "small", + pageSize: this.state.pageSize, + showSizeChanger: true, + pageSizeOptions: this.state.pageSizeOptions + }} + scroll={{ x: this.state.isNarrowWindow ? undefined : 1200 }}> + + title="Name" + dataIndex={nameof("name")} + sorter={(a, b) => a.name.localeCompare(b.name)} + defaultSortOrder={"ascend"} + width={this.state.isNarrowWindow ? undefined : 200} + className={styles.nogrow} + fixed="left" + render={(text: string) =>
{text}
} /> + {this.state.isNarrowWindow + ? null + : + title="Description" + dataIndex={nameof("description")} + className={styles.nogrow} + render={(_text: string, record: List) => } />} + {this.state.isNarrowWindow + ? null + : + title="Software" + dataIndex={nameof("syntaxId")} + className={styles.nogrow} + render={(text: string) =>
{text}
} />} + {this.state.isNarrowWindow + ? null + : + title="Languages" + dataIndex={nameof("languageIds")} + sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, this.state.languages)} + width={125} + className={styles.nogrow} + render={(languageIds: number[]) => + languageIds + ? languageIds.includes(l.id))} /> + : null} />} + {this.state.isNarrowWindow + ? null + : + title="Tags" + dataIndex={nameof("tagIds")} + sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, this.state.tags)} + width={275} + className={styles.nogrow} + render={(tagIds: number[]) => + tagIds + ? tagIds.includes(t.id))} /> + : null} />} + + title="Details" + dataIndex={nameof("viewUrl")} + className={styles.nogrow} + fixed="right" + render={(_text: string, record: List) => } /> + + { + const list = this.state.lists.find(l => l.id === +props.match.params.id); + return list + ? + : null //TODO: redirect or 404 for invalid list id + }} /> +
+ ); + } + + componentWillUnmount() { + window.removeEventListener('resize', this.updatePageSize); + } +} + +interface ArraySortableEntity { + id: number; + name: string; +} + +const arraySorter = (a: number[], b: number[], entities: ArraySortableEntity[]): number => + a && a.length + ? b && b.length + ? a.length === b.length + ? entities.filter((e: ArraySortableEntity) => a.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() + > entities.filter((e: ArraySortableEntity) => b.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() + ? 1 + : -1 + : a.length > b.length + ? -1 + : 1 + : -1 + : 1; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listsTable/index.ts b/src/FilterLists.Web.V2/src/components/listsTable/index.ts new file mode 100644 index 000000000..ad67ef839 --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/listsTable/index.ts @@ -0,0 +1,3 @@ +import { ListsTable } from './ListsTable'; + +export { ListsTable } \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.module.css b/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.module.css rename to src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.module.css diff --git a/src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/buttons/subscribe/SubscribeButton.tsx rename to src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.tsx diff --git a/src/FilterLists.Web.V2/src/components/buttons/subscribe/index.ts b/src/FilterLists.Web.V2/src/components/subscribeButton/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/buttons/subscribe/index.ts rename to src/FilterLists.Web.V2/src/components/subscribeButton/index.ts From 8185a34676265a78cc84ef7b4ad84af65aed3f2f Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 17:12:43 -0500 Subject: [PATCH 099/163] add list title to details drawer --- src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx index 92ce66130..d1d15f286 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -14,6 +14,7 @@ export const ListDetailsDrawer = (props: RouteComponentProps & Props) => props.history.push("/")}> +

{props.list.name}

; \ No newline at end of file From 7087e100ba6551da7afb0bbd3908debdc137d262 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 17:19:57 -0500 Subject: [PATCH 100/163] update document title on drawer open/close --- .../src/components/ListDetailsDrawer.tsx | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx index d1d15f286..203937a1e 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -10,11 +10,33 @@ interface Props { list: List; }; -export const ListDetailsDrawer = (props: RouteComponentProps & Props) => - props.history.push("/")}> -

{props.list.name}

- - -
; \ No newline at end of file +interface State { + baseDocumentTitle: string; +} + +export class ListDetailsDrawer extends React.Component { + constructor(props: any) { + super(props); + this.state = { + baseDocumentTitle: document.title + }; + } + + componentDidMount() { + document.title = this.props.list.name + " | " + this.state.baseDocumentTitle + } + + render() { + return this.props.history.push("/")}> +

{this.props.list.name}

+ + +
+ } + + componentWillUnmount() { + document.title = this.state.baseDocumentTitle + } +} \ No newline at end of file From a9f6074efdce89581fc320ace1a121a22666192e Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 17:28:47 -0500 Subject: [PATCH 101/163] redirect on invalid lists id route --- .../src/components/listsTable/ListsTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index d55644291..780cfdc6e 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -1,6 +1,6 @@ import { Table } from 'antd'; import React from 'react'; -import { Route, RouteComponentProps } from 'react-router-dom'; +import { Redirect, Route, RouteComponentProps } from 'react-router-dom'; import { Language } from '../../interfaces/Language'; import { List } from '../../interfaces/List'; @@ -141,7 +141,7 @@ export class ListsTable extends React.Component { const list = this.state.lists.find(l => l.id === +props.match.params.id); return list ? - : null //TODO: redirect or 404 for invalid list id + : }} /> ); From 7546c7e65582ec4c980af7732a3a49947c8490b0 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 18:24:03 -0500 Subject: [PATCH 102/163] add languages and tags clouds to details drawer --- .../src/components/ListDetailsDrawer.tsx | 16 +++++++++++++++- .../components/languageCloud/LanguageCloud.tsx | 2 ++ .../src/components/listsTable/ListsTable.tsx | 2 +- .../src/components/tagCloud/TagCloud.tsx | 2 ++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx index 203937a1e..e9228ada5 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -2,12 +2,18 @@ import { Drawer } from 'antd'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; +import { Language } from '../interfaces/Language'; import { List } from '../interfaces/List'; +import { Tag } from '../interfaces/Tag'; import { Description } from './Description'; +import { LanguageCloud } from './languageCloud'; import { SubscribeButton } from './subscribeButton'; +import { TagCloud } from './tagCloud'; interface Props { list: List; + languages: Language[]; + tags: Tag[]; }; interface State { @@ -29,9 +35,17 @@ export class ListDetailsDrawer extends React.Component this.props.history.push("/")}> -

{this.props.list.name}

+ {this.props.list.languageIds + ? this.props.list.languageIds.includes(l.id))} showLabel={true} /> + : null} + {this.props.list.tagIds + ? this.props.list.tagIds.includes(t.id))} showLabel={true} /> + : null} } diff --git a/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx b/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx index 44c474942..d0d09f425 100644 --- a/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx +++ b/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx @@ -10,11 +10,13 @@ interface LanguageData { interface Props { languages: LanguageData[] + showLabel?: boolean }; export const LanguageCloud = (props: Props): JSX.Element | null => props.languages && props.languages.length ?
+ {props.showLabel &&

{`Language${props.languages.length > 1 ? "s" : ""}:`}

} {props.languages.map((l: LanguageData, i: number) => {l.iso6391})}
diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index 780cfdc6e..6521ad30a 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -140,7 +140,7 @@ export class ListsTable extends React.Component { { const list = this.state.lists.find(l => l.id === +props.match.params.id); return list - ? + ? : }} /> diff --git a/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx b/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx index 9c93523c7..48dbed300 100644 --- a/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx +++ b/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx @@ -10,11 +10,13 @@ interface TagData { interface Props { tags: TagData[] + showLabel?: boolean }; export const TagCloud = (props: Props): JSX.Element | null => props.tags && props.tags.length ?
+ {props.showLabel &&

{`Tag${props.tags.length > 1 ? "s" : ""}:`}

} {props.tags.map((t: TagData, i: number) => {t.name})}
From 60711b53e48f419b9f52c9324bbdadd016193a04 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 25 Aug 2019 20:54:04 -0500 Subject: [PATCH 103/163] add link buttons to drawer, ditch dropdown button for subscribe --- .../src/components/LinkButton.tsx | 23 +++++ .../src/components/ListDetailsButton.tsx | 1 + .../src/components/ListDetailsDrawer.tsx | 56 ++++++++++- .../src/components/SubscribeButton.tsx | 67 +++++++++++++ .../SubscribeButton.module.css | 14 --- .../subscribeButton/SubscribeButton.tsx | 96 ------------------- .../src/components/subscribeButton/index.ts | 3 - 7 files changed, 144 insertions(+), 116 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/components/LinkButton.tsx create mode 100644 src/FilterLists.Web.V2/src/components/SubscribeButton.tsx delete mode 100644 src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.module.css delete mode 100644 src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.tsx delete mode 100644 src/FilterLists.Web.V2/src/components/subscribeButton/index.ts diff --git a/src/FilterLists.Web.V2/src/components/LinkButton.tsx b/src/FilterLists.Web.V2/src/components/LinkButton.tsx new file mode 100644 index 000000000..94d4da593 --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/LinkButton.tsx @@ -0,0 +1,23 @@ +import { Button } from 'antd'; +import { ButtonType } from 'antd/lib/button'; +import React from 'react'; + +interface Props { + url: string; + text: string; + title?: string; + type?: ButtonType; + icon?: string; +}; + +export const LinkButton = (props: Props) => + ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx index 18e90ff58..168e64a55 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx @@ -11,6 +11,7 @@ interface Props { export const ListDetailsButton = (props: RouteComponentProps & Props) => ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx index e9228ada5..c37840f0e 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -1,4 +1,5 @@ -import { Drawer } from 'antd'; +import { Divider, Drawer } from 'antd'; +import ButtonGroup from 'antd/lib/button/button-group'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; @@ -7,7 +8,8 @@ import { List } from '../interfaces/List'; import { Tag } from '../interfaces/Tag'; import { Description } from './Description'; import { LanguageCloud } from './languageCloud'; -import { SubscribeButton } from './subscribeButton'; +import { LinkButton } from './LinkButton'; +import { SubscribeButton } from './SubscribeButton'; import { TagCloud } from './tagCloud'; interface Props { @@ -46,7 +48,55 @@ export class ListDetailsDrawer extends React.Component this.props.list.tagIds.includes(t.id))} showLabel={true} /> : null} - + + + {this.props.list.viewUrl && } + {this.props.list.viewUrl && + } + {this.props.list.homeUrl && + } + {this.props.list.policyUrl && + } + {this.props.list.emailAddress && + } + {this.props.list.issuesUrl && + } + {this.props.list.submissionUrl && + } + {this.props.list.forumUrl && + } + {this.props.list.chatUrl && + } + {this.props.list.donateUrl && + } + } diff --git a/src/FilterLists.Web.V2/src/components/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/components/SubscribeButton.tsx new file mode 100644 index 000000000..2fc226c62 --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/SubscribeButton.tsx @@ -0,0 +1,67 @@ +import { Button } from 'antd'; +import { ButtonProps, ButtonType } from 'antd/lib/button'; +import React from 'react'; + +interface Props { + name: string; + viewUrl: string; + viewUrlMirrors: string[]; +}; + +export const SubscribeButton = (props: Props): JSX.Element => { + const buttonProps = buildButtonProps(props.name, props.viewUrl); + return + + {props.viewUrlMirrors && props.viewUrlMirrors.length && + props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => { + const buttonProps = buildButtonProps(props.name, viewUrlMirror); + return + })} + +}; + +const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => { + let type: ButtonType = "primary"; + let disabled: boolean = false; + + const hrefLocation = `${encodeURIComponent(viewUrl)}`; + const hrefTitle = `${encodeURIComponent(name)}`; + let href = `abp:subscribe?location=${hrefLocation}&title=${hrefTitle}`; + + let prefixes: string[] = []; + let message = `Subscribe to ${name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; + + // HTTP protocols + if (viewUrl.includes(".onion/")) { + type = "dashed"; + prefixes.push("TOR"); + } + if (viewUrl.includes("http://")) { + type = "danger"; + prefixes.push("INSECURE"); + } + + // Software protocols + if (viewUrl.includes(".tpl")) { + disabled = true; // IE not supported by FilterLists + } + if (viewUrl.includes(".lsrules") || viewUrl.includes("?hostformat=littlesnitch")) { + href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; + message = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; + } + + const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`; + + return [{ type, href, title }, disabled] +} diff --git a/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.module.css b/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.module.css deleted file mode 100644 index 8cea8c069..000000000 --- a/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.module.css +++ /dev/null @@ -1,14 +0,0 @@ -.sub_li { - /* reduce vertical white space around dropdown items */ - height: 24px !important; -} - -.sub_a { - /* fix font color on dropdown buttons */ - color: #fff !important; -} - -.single { - /* make non-dropdown button equivalent width to dropdown */ - width: 106.81px; -} diff --git a/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.tsx deleted file mode 100644 index 41a587c36..000000000 --- a/src/FilterLists.Web.V2/src/components/subscribeButton/SubscribeButton.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { Button, Dropdown, Menu } from 'antd'; -import { ButtonProps, ButtonType } from 'antd/lib/button'; -import React from 'react'; - -import styles from './SubscribeButton.module.css'; - -//TODO: import DropdownButtonType from antd rather than redefining if they export the type -//import { DropdownButtonType } from "antd/lib/dropdown"; -declare type DropdownButtonType = 'primary' | 'ghost' | 'dashed'; - -interface Props { - name: string; - viewUrl: string; - viewUrlMirrors: string[]; -}; - -export const SubscribeButton = (props: Props): JSX.Element => { - const buttonProps = buildButtonProps(props.name, props.viewUrl); - return (props.viewUrlMirrors && props.viewUrlMirrors.length) - ? - :
- -
-}; - -const ButtonDropdown = (props: Props): JSX.Element => { - const buttonProps = buildButtonProps(props.name, props.viewUrl); - return }> - Subscribe - ; -}; - -interface DropdownOverlayProps { - name: string; - viewUrlMirrors: string[]; -}; - -const DropdownOverlay = (props: DropdownOverlayProps): JSX.Element => - - {props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => { - const buttonProps = buildButtonProps(props.name, viewUrlMirror); - return - - - })} - ; - -const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => { - let type: ButtonType = "primary"; - let disabled: boolean = false; - - const hrefLocation = `${encodeURIComponent(viewUrl)}`; - const hrefTitle = `${encodeURIComponent(name)}`; - let href = `abp:subscribe?location=${hrefLocation}&title=${hrefTitle}`; - - let prefixes: string[] = []; - let message = `Subscribe to ${name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; - - // HTTP protocols - if (viewUrl.includes(".onion/")) { - type = "dashed"; - prefixes.push("TOR"); - } - if (viewUrl.includes("http://")) { - type = "danger"; - prefixes.push("INSECURE"); - } - - // Software protocols - if (viewUrl.includes(".tpl")) { - disabled = true; // IE not supported by FilterLists - } - if (viewUrl.includes(".lsrules") || viewUrl.includes("?hostformat=littlesnitch")) { - href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; - message = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; - } - - const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`; - - return [{ type, href, title }, disabled] -} diff --git a/src/FilterLists.Web.V2/src/components/subscribeButton/index.ts b/src/FilterLists.Web.V2/src/components/subscribeButton/index.ts deleted file mode 100644 index 08f333155..000000000 --- a/src/FilterLists.Web.V2/src/components/subscribeButton/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { SubscribeButton } from './SubscribeButton'; - -export { SubscribeButton } \ No newline at end of file From b3c793405c53d3f45209083da294ca157d9de0c8 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 12:35:43 -0500 Subject: [PATCH 104/163] add published date to drawer --- src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx index c37840f0e..ec75ef904 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -48,6 +48,12 @@ export class ListDetailsDrawer extends React.Component this.props.list.tagIds.includes(t.id))} showLabel={true} /> : null} + {this.props.list.publishedDate + ?
+

First Published Date:

+ {new Date(this.props.list.publishedDate).toDateString()} +
+ : null} {this.props.list.viewUrl && } From 20196242671bb2f20d41364409a6ea9b4b5aee1a Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 12:39:42 -0500 Subject: [PATCH 105/163] hacky fix for table-shift when details drawer is opened --- src/FilterLists.Web.V2/src/index.css | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/index.css b/src/FilterLists.Web.V2/src/index.css index 4a1df4db7..b54726560 100644 --- a/src/FilterLists.Web.V2/src/index.css +++ b/src/FilterLists.Web.V2/src/index.css @@ -1,13 +1,17 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + + /* hacky fix for table-shift when details drawer is opened */ + width: calc(100%) !important; + overflow: auto !important; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } From 2b8ae9f9e2d7dd2d45f4ae92fe5917fbb296eb9f Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 12:53:02 -0500 Subject: [PATCH 106/163] wait until lists retrieved from api before redirecting on 'invalid' list url --- src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index 6521ad30a..8f0504279 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -141,7 +141,7 @@ export class ListsTable extends React.Component { const list = this.state.lists.find(l => l.id === +props.match.params.id); return list ? - : + : this.state.lists && this.state.lists.length && }} /> ); From 885513d96a0fb2a4725caff5cc997620988f15d1 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 12:58:44 -0500 Subject: [PATCH 107/163] speed up navigation to/from drawers --- src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx | 4 +++- src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx | 2 ++ src/FilterLists.Web.V2/src/index.css | 4 ---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx index 168e64a55..df308e8bd 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx @@ -12,6 +12,8 @@ export const ListDetailsButton = (props: RouteComponentProps & Props) => ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx index ec75ef904..39a4fba5e 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -38,6 +38,8 @@ export class ListDetailsDrawer extends React.Component this.props.history.push("/")}> diff --git a/src/FilterLists.Web.V2/src/index.css b/src/FilterLists.Web.V2/src/index.css index b54726560..ec2585e8c 100644 --- a/src/FilterLists.Web.V2/src/index.css +++ b/src/FilterLists.Web.V2/src/index.css @@ -5,10 +5,6 @@ body { sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - - /* hacky fix for table-shift when details drawer is opened */ - width: calc(100%) !important; - overflow: auto !important; } code { From d0407d85573cbb238a9e1376c950f80eff7989c1 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 13:06:00 -0500 Subject: [PATCH 108/163] fix title update on fast drawer change --- .../src/components/ListDetailsDrawer.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx index 39a4fba5e..ecd1cd82b 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -30,10 +30,6 @@ export class ListDetailsDrawer extends React.Component } + componentDidUpdate() { + document.title = this.props.list.name + " | " + this.state.baseDocumentTitle + } + componentWillUnmount() { document.title = this.state.baseDocumentTitle } From b6b8ef9a317e45a29c9c0000c5251c32159a8b13 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 13:13:51 -0500 Subject: [PATCH 109/163] make drawer not cover critical controls for quick navigation --- .../src/components/ListDetailsDrawer.tsx | 2 +- .../src/components/listsTable/ListsTable.tsx | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx index ecd1cd82b..9a8fb3d43 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx @@ -34,7 +34,7 @@ export class ListDetailsDrawer extends React.Component { size="small" pagination={{ size: "small", + style: { float: "left" }, pageSize: this.state.pageSize, showSizeChanger: true, pageSizeOptions: this.state.pageSizeOptions }} scroll={{ x: this.state.isNarrowWindow ? undefined : 1200 }}> + + title="Details" + dataIndex={nameof("viewUrl")} + className={styles.nogrow} + fixed="left" + render={(_text: string, record: List) => } /> title="Name" dataIndex={nameof("name")} @@ -130,12 +137,6 @@ export class ListsTable extends React.Component { tagIds ? tagIds.includes(t.id))} /> : null} />} - - title="Details" - dataIndex={nameof("viewUrl")} - className={styles.nogrow} - fixed="right" - render={(_text: string, record: List) => } /> { const list = this.state.lists.find(l => l.id === +props.match.params.id); From 3253640f283d94f83a81ad1b3dfa4955528e87e5 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 13:31:07 -0500 Subject: [PATCH 110/163] simple pagination, set title on drawer mount, ren details -> info --- ...stDetailsButton.tsx => ListInfoButton.tsx} | 8 +++---- ...stDetailsDrawer.tsx => ListInfoDrawer.tsx} | 12 +++++++++-- .../src/components/listsTable/ListsTable.tsx | 21 +++++++------------ 3 files changed, 22 insertions(+), 19 deletions(-) rename src/FilterLists.Web.V2/src/components/{ListDetailsButton.tsx => ListInfoButton.tsx} (69%) rename src/FilterLists.Web.V2/src/components/{ListDetailsDrawer.tsx => ListInfoDrawer.tsx} (94%) diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx similarity index 69% rename from src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx rename to src/FilterLists.Web.V2/src/components/ListInfoButton.tsx index df308e8bd..efa70a457 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx @@ -8,12 +8,12 @@ interface Props { list: List; }; -export const ListDetailsButton = (props: RouteComponentProps & Props) => +export const ListInfoButton = (props: RouteComponentProps & Props) => ; \ No newline at end of file + : props.history.push(`/lists/${props.list.id}`)} > + Info + ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx similarity index 94% rename from src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx rename to src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx index 9a8fb3d43..58d7788d8 100644 --- a/src/FilterLists.Web.V2/src/components/ListDetailsDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx @@ -22,7 +22,7 @@ interface State { baseDocumentTitle: string; } -export class ListDetailsDrawer extends React.Component { +export class ListInfoDrawer extends React.Component { constructor(props: any) { super(props); this.state = { @@ -30,6 +30,10 @@ export class ListDetailsDrawer extends React.Component { languages: [], tags: [], pageSize: 0, - pageSizeOptions: [], isNarrowWindow: false }; this.updatePageSize = this.updatePageSize.bind(this); @@ -60,10 +58,8 @@ export class ListsTable extends React.Component { } private updatePageSize() { - const pageSize = Math.floor((window.innerHeight - 211.5) / 56); this.setState({ - pageSize: pageSize, - pageSizeOptions: [pageSize, 200, 2000].sort((a, b) => a - b).map(String), + pageSize: Math.floor((window.innerHeight - 211.5) / 56), isNarrowWindow: window.innerWidth < 576 ? true : false }); } @@ -78,18 +74,17 @@ export class ListsTable extends React.Component { size="small" pagination={{ size: "small", + simple: true, style: { float: "left" }, - pageSize: this.state.pageSize, - showSizeChanger: true, - pageSizeOptions: this.state.pageSizeOptions + pageSize: this.state.pageSize }} scroll={{ x: this.state.isNarrowWindow ? undefined : 1200 }}> - title="Details" + title="Info" dataIndex={nameof("viewUrl")} className={styles.nogrow} fixed="left" - render={(_text: string, record: List) => } /> + render={(_text: string, record: List) => } /> title="Name" dataIndex={nameof("name")} @@ -141,7 +136,7 @@ export class ListsTable extends React.Component { { const list = this.state.lists.find(l => l.id === +props.match.params.id); return list - ? + ? : this.state.lists && this.state.lists.length && }} /> From 8f0d579498b9695f126c24ccf84c394730919caf Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 18:15:54 -0500 Subject: [PATCH 111/163] tweak text on Subscribe button for mirrors --- src/FilterLists.Web.V2/src/components/SubscribeButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/components/SubscribeButton.tsx b/src/FilterLists.Web.V2/src/components/SubscribeButton.tsx index 2fc226c62..765554158 100644 --- a/src/FilterLists.Web.V2/src/components/SubscribeButton.tsx +++ b/src/FilterLists.Web.V2/src/components/SubscribeButton.tsx @@ -25,7 +25,7 @@ export const SubscribeButton = (props: Props): JSX.Element => { block icon="import" {...buttonProps[0]}> - {`Mirror ${i + 1} Subscribe`} + {`Subscribe (Mirror ${i + 1})`} })} From 7d37ae6e22584a568e785e0017a402e0cce7d733 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 26 Aug 2019 21:04:49 -0500 Subject: [PATCH 112/163] tweak ListInfoButton --- .../src/components/ListInfoButton.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx index efa70a457..80a223d8e 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx @@ -1,4 +1,4 @@ -import { Button } from 'antd'; +import { Button, Icon } from 'antd'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; @@ -8,12 +8,14 @@ interface Props { list: List; }; -export const ListInfoButton = (props: RouteComponentProps & Props) => - ; \ No newline at end of file + : props.history.push(listPath)} > + + +}; \ No newline at end of file From 91dde97533751ccf6911a0416f1ae8cf31166a1a Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 27 Aug 2019 06:58:41 -0500 Subject: [PATCH 113/163] wip fetch licenses --- .../src/components/listsTable/ListsTable.tsx | 8 ++++++++ src/FilterLists.Web.V2/src/interfaces/License.ts | 6 ++++++ 2 files changed, 14 insertions(+) create mode 100644 src/FilterLists.Web.V2/src/interfaces/License.ts diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index e547a7b00..ca403032d 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { Redirect, Route, RouteComponentProps } from 'react-router-dom'; import { Language } from '../../interfaces/Language'; +import { License } from '../../interfaces/License'; import { List } from '../../interfaces/List'; import { Tag } from '../../interfaces/Tag'; import { nameof } from '../../utils'; @@ -16,6 +17,7 @@ import styles from './ListsTable.module.css'; interface State { lists: List[]; languages: Language[]; + licenses: License[]; tags: Tag[]; pageSize: number; isNarrowWindow: boolean; @@ -27,6 +29,7 @@ export class ListsTable extends React.Component { this.state = { lists: [], languages: [], + licenses: [], tags: [], pageSize: 0, isNarrowWindow: false @@ -55,6 +58,11 @@ export class ListsTable extends React.Component { .then(response => response.json()) .then(json => (json as Tag[]).sort((a, b) => a.name.localeCompare(b.name))) .then(tags => { this.setState({ tags: tags }); }) + + // fetch("/api/v1/licenses") + // .then(response => response.json()) + // .then(json => (json as License[]).sort((a, b) => a.name.localeCompare(b.name))) + // .then(licenses => { this.setState({ licenses: licenses }); }) } private updatePageSize() { diff --git a/src/FilterLists.Web.V2/src/interfaces/License.ts b/src/FilterLists.Web.V2/src/interfaces/License.ts new file mode 100644 index 000000000..ba223d799 --- /dev/null +++ b/src/FilterLists.Web.V2/src/interfaces/License.ts @@ -0,0 +1,6 @@ +export interface License { + id: number; + descriptionUrl: string; + filterListIds: number[]; + name: string; +}; \ No newline at end of file From 8c22f74116972071fcf63f4e9fd0a0fc52a63b9b Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 27 Aug 2019 12:57:24 -0500 Subject: [PATCH 114/163] add license to drawer --- src/FilterLists.Web.V2/package-lock.json | Bin 562449 -> 561905 bytes .../src/components/LicenseTag.tsx | 26 ++++++++++++++++++ .../src/components/ListInfoDrawer.tsx | 10 +++++-- .../src/components/listsTable/ListsTable.tsx | 15 ++++++---- .../src/components/tagCloud/TagCloud.tsx | 10 ++----- 5 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/components/LicenseTag.tsx diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index 1f6d43ece995aaf730ab3f40acbce16fb81f4419..877afcf52e40b4bdd0c8a2fc11c38c71caa56364 100644 GIT binary patch delta 248 zcmbQZO6lWLrG^&97N!>FEi6V^(=`N{WVh#MvGg!azre*LxBbsYMps6#==8eJjL#tQ z_wre0ac`ed&BDtFRyAGRlS6s>0Tw2u=?fH?xuz$Wuy9QO%gA&EBFoRrG#O&VhFTVu z=?e8Mk<%Myu;@;oC(g>geF6(p2h5G3Eg2k((~i#qtc|mhb#b zv%rF~+s{cb2{CVzVPa<5o-mUoj|F1FEi6V^(>LU@*lzdFV(DR;zJZI$Zu_5)jERPm4GxJ;4_L^; U+CF6t3lM{7w(V2qu*ZG_0BtTB+W-In diff --git a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx new file mode 100644 index 000000000..a69cb9f2e --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx @@ -0,0 +1,26 @@ +import { Tag } from 'antd'; +import * as React from 'react'; + +import { License } from '../interfaces/License'; + +interface Props { + license: License; + showLabel?: boolean +}; + +export const LicenseTag = (props: Props): JSX.Element | null => + props.license && props.license.name + ?
+ {props.showLabel &&

License:

} + + + +
+ : null; + +const TagContents = (props: Props): JSX.Element => + props.license.descriptionUrl + ? + {props.license.name} + + : {props.license.name} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx index 58d7788d8..db10f89c0 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx @@ -4,10 +4,12 @@ import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { Language } from '../interfaces/Language'; +import { License } from '../interfaces/License'; import { List } from '../interfaces/List'; import { Tag } from '../interfaces/Tag'; import { Description } from './Description'; import { LanguageCloud } from './languageCloud'; +import { LicenseTag } from './LicenseTag'; import { LinkButton } from './LinkButton'; import { SubscribeButton } from './SubscribeButton'; import { TagCloud } from './tagCloud'; @@ -15,6 +17,7 @@ import { TagCloud } from './tagCloud'; interface Props { list: List; languages: Language[]; + license?: License; tags: Tag[]; }; @@ -45,10 +48,13 @@ export class ListInfoDrawer extends React.Component this.props.history.push("/")}> {this.props.list.languageIds - ? this.props.list.languageIds.includes(l.id))} showLabel={true} /> + ? : null} {this.props.list.tagIds - ? this.props.list.tagIds.includes(t.id))} showLabel={true} /> + ? + : null} + {this.props.license + ? : null} {this.props.list.publishedDate ?
diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index ca403032d..b0b657d89 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -59,10 +59,10 @@ export class ListsTable extends React.Component { .then(json => (json as Tag[]).sort((a, b) => a.name.localeCompare(b.name))) .then(tags => { this.setState({ tags: tags }); }) - // fetch("/api/v1/licenses") - // .then(response => response.json()) - // .then(json => (json as License[]).sort((a, b) => a.name.localeCompare(b.name))) - // .then(licenses => { this.setState({ licenses: licenses }); }) + fetch("/api/v1/licenses") + .then(response => response.json()) + .then(json => (json as License[]).sort((a, b) => a.name.localeCompare(b.name))) + .then(licenses => { this.setState({ licenses: licenses }); }) } private updatePageSize() { @@ -144,7 +144,12 @@ export class ListsTable extends React.Component { { const list = this.state.lists.find(l => l.id === +props.match.params.id); return list - ? + ? list.languageIds.includes(l.id))} + license={list.licenseId ? this.state.licenses.find((l: License) => list.licenseId === l.id) : undefined} + tags={list.tagIds && this.state.tags.filter((t: Tag) => list.tagIds.includes(t.id))} + {...this.props} /> : this.state.lists && this.state.lists.length && }} /> diff --git a/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx b/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx index 48dbed300..c63c775f4 100644 --- a/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx +++ b/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx @@ -1,15 +1,11 @@ import { Tag } from 'antd'; import React from 'react'; +import { Tag as TagInterface } from '../../interfaces/Tag'; import styles from './TagCloud.module.css'; -interface TagData { - description: string; - name: string; -}; - interface Props { - tags: TagData[] + tags: TagInterface[] showLabel?: boolean }; @@ -17,7 +13,7 @@ export const TagCloud = (props: Props): JSX.Element | null => props.tags && props.tags.length ?
{props.showLabel &&

{`Tag${props.tags.length > 1 ? "s" : ""}:`}

} - {props.tags.map((t: TagData, i: number) => + {props.tags.map((t: TagInterface, i: number) => {t.name})}
: null; \ No newline at end of file From c74a46288b8bcf7b18b837727f91a85c327d3694 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Fri, 30 Aug 2019 19:26:40 -0500 Subject: [PATCH 115/163] update pkgs --- src/FilterLists.Web.V2/package-lock.json | Bin 561905 -> 562496 bytes src/FilterLists.Web.V2/package.json | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index 877afcf52e40b4bdd0c8a2fc11c38c71caa56364..f454712090df464cdf087440fe52dde3aaad7fd8 100644 GIT binary patch delta 1046 zcmWlWOK9760LGCYayFWlY>YuJSrhNUL@QbH6PAG=@xt2im!i$T)r zGh=x&EYwP-UZx8!%{tE1CxgR9H0Sm@a{@P7{D;OFZQ47l4+ z2>f{q+5~?k0vq5d4F`qHyiVoGj3bE7wAtVmL)Sp%x!jpfjV?}h+giUSnvx^zQ0<~i z*>OWyq_J{Z&rM8wPV%Z&vO7#%700H?VzUV&jJVnP;BViVT=e!|3++ALhtB0&KHm5D zPr->6*j{p@z%3s*dC~Xo^4~M474fj|UICRa0>Qn*qrmd;DER&pDB`U>kAk-r@H)8h z=E|mbHxv;1O@?Tg-6n^12`QOLMCc0Eo~2@>jGO5SZw;FcJy8crS?5NAgvO&aV~{(~ z=mOqMYSf5su)|>{HpOeTS`W$OlImy<&b|+X!BZE$3QqRmAo%HHcy+nq!2i4ePTvXO zpnMZvhmzjGY)jxJM7OgGOT|0)C*N#I1 z3&p_?afkrFJqxWvaqs%Wu%K$yXc?j6+QcFj=RJ~$!5QM*)mVh#)1!pYHz_mMlE_$v xaU^`4HOA_oPZ%~g<4QfYn{F`G28ZV(g-RzfW^%Y)PJ>_kD=#lUc^>M2_8$QbZ65#t delta 1264 zcmXYvTZ|KB6vy*Tr&F$5mIx@y#bqJH24~v2wGR@f?QFZf&9t3qJAF`knck75`V z;1UJ1SdtG6K@vn!K}aCX3o*neBaw(c8PUWCdGSG4jF-TJyQ~i<=XXy2=lsvZx&6u1 z!o{iii{tsbYvAXvns$%Ro7SBCWj&;Cf_3osBc_c~o-Nu%n$#mRLy7VYGmMjDRF;t1 zrA8uc^H*M7W_Sh0^$B zWyj%Dz&Hhf6~J#9K#uW;7`%^wN!UJ$OiM#WuoakcDb05xqBoa}#O#G?L-H2L5f>zD z9Ow3qR8ku;qA;9Q+c`f`G3iH4M|2Ph&;HJmO4w;;3uzJAZ*I4_|o(RNQHO%2W8=!6NMlhg_`sEDm z9*pE@jCbpdCpN70JH2SjsgbUvv)-)vD1~jO`+}#QFVW#qOp0s%=6Le?7v8N;j8AO0 z%-uNw76UQvoG=yd!`+j}7Nb!?k0bD#RmfK3@dDt%lP-MiA$YJ%jms9RaqUm=_G;tw zesnEZmVO8j+cH9{2^lX-uN^>9xcwliz}HWsd*HcEW{WY8BFFw0zWfhBq3{&4!g&7> zO0HO%*$UUag+5qb`L`8$?@4nDJpZEwHLR!53DeEz5EEkTJA>BIWskd4NN|ZJ;NF|q z#xe252H3oSn&)nuLya5f%=>--E_iS8m*DIO+q}s3f6Y6kYM`P9iiNDVm8c|Ac04M@ z3UO8}ds-w{*Hoq9q=;N1*Y!}%REw%oLoOQDJ&qpj7E`HwrtcxBUVSJ~c*`HnX9q4W zk|~cDuI_->E@C7+e+yd+zk36l9A8+u9$vYHZG*pkjIB1_*^hm;68=>H4rraj%uqjy zZGhKbLAJs9^}sCgYQUCK)AnB9lchB^IdqbRUP@!7h}hTT0&iy(g58ZMSn zZtrZK$uPP%P-r(KM^i|4@P<&YQh1)P`Dh Date: Fri, 30 Aug 2019 19:48:02 -0500 Subject: [PATCH 116/163] rm explicit return types, misc. linting --- src/FilterLists.Web.V2/src/App.tsx | 14 +++---- .../src/components/Description.tsx | 2 +- .../src/components/LicenseTag.tsx | 4 +- .../src/components/ListInfoButton.tsx | 2 +- .../src/components/SubscribeButton.tsx | 2 +- .../languageCloud/LanguageCloud.tsx | 12 ++---- .../src/components/listsTable/ListsTable.tsx | 40 ++++++++++--------- .../src/components/tagCloud/TagCloud.tsx | 2 +- src/FilterLists.Web.V2/src/index.css | 6 +-- src/FilterLists.Web.V2/src/utils/nameof.ts | 2 +- 10 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index 73523b53e..c04abd8ce 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -27,18 +27,18 @@ export const App: React.FC = () => ; -const Logo = (): JSX.Element => +const Logo = () => FilterLists logo; -const NotFound = (props: RouteComponentProps): JSX.Element => +const NotFound = (props: RouteComponentProps) =>

404 Not Found: {props.location.pathname}

; -const CopyrightAuthor = (): JSX.Element => +const CopyrightAuthor = () => ©{new Date().getFullYear()}  Collin M. Barrett ; -const Community = (): JSX.Element => +const Community = () => Community ; -const GitHub = (): JSX.Element => +const GitHub = () => GitHub ; -const Api = (): JSX.Element => +const Api = () => API ; -const Donate = (): JSX.Element => +const Donate = () => diff --git a/src/FilterLists.Web.V2/src/components/Description.tsx b/src/FilterLists.Web.V2/src/components/Description.tsx index a2862dbf7..abfb70937 100644 --- a/src/FilterLists.Web.V2/src/components/Description.tsx +++ b/src/FilterLists.Web.V2/src/components/Description.tsx @@ -5,7 +5,7 @@ interface Props { descriptionSourceUrl: string; }; -export const Description = (props: Props): JSX.Element => +export const Description = (props: Props) => props.description ?
{props.description}
:

{props.description}

; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx index a69cb9f2e..80a527e07 100644 --- a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx +++ b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx @@ -8,7 +8,7 @@ interface Props { showLabel?: boolean }; -export const LicenseTag = (props: Props): JSX.Element | null => +export const LicenseTag = (props: Props) => props.license && props.license.name ?
{props.showLabel &&

License:

} @@ -18,7 +18,7 @@ export const LicenseTag = (props: Props): JSX.Element | null =>
: null; -const TagContents = (props: Props): JSX.Element => +const TagContents = (props: Props) => props.license.descriptionUrl ?
{props.license.name} diff --git a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx index 80a223d8e..d17d0a21c 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx @@ -8,7 +8,7 @@ interface Props { list: List; }; -export const ListInfoButton = (props: RouteComponentProps & Props): JSX.Element => { +export const ListInfoButton = (props: RouteComponentProps & Props) => { const listPath = `/lists/${props.list.id}`; return - {props.viewUrlMirrors && props.viewUrlMirrors.length && - props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => { + return ( + <> + + + + ) +}; + +const PrimaryButton = (props: [ButtonProps, boolean]) => + ; + +const MirrorButtons = (props: Props) => + <> + {props.viewUrlMirrors && props.viewUrlMirrors.length + ? props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => { const buttonProps = buildButtonProps(props.name, viewUrlMirror); return - })} - -}; + }) + : null} + ; const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => { let type: ButtonType = "primary"; From 1230129a4b0e3acd7bd7e3a8c5c8675697cb5b39 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 13:07:53 -0500 Subject: [PATCH 124/163] refactor SubscribeButton for SRP -> Primary Button & MirrorButtons --- .../src/components/ListInfoDrawer.tsx | 4 +- ...bscribeButton.tsx => SubscribeButtons.tsx} | 59 +++++++++++-------- 2 files changed, 38 insertions(+), 25 deletions(-) rename src/FilterLists.Web.V2/src/components/{SubscribeButton.tsx => SubscribeButtons.tsx} (67%) diff --git a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx index db10f89c0..54fe5df6f 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx @@ -11,7 +11,7 @@ import { Description } from './Description'; import { LanguageCloud } from './languageCloud'; import { LicenseTag } from './LicenseTag'; import { LinkButton } from './LinkButton'; -import { SubscribeButton } from './SubscribeButton'; +import { SubscribeButtons } from './SubscribeButtons'; import { TagCloud } from './tagCloud'; interface Props { @@ -64,7 +64,7 @@ export class ListInfoDrawer extends React.Component - {this.props.list.viewUrl && } + {this.props.list.viewUrl && } {this.props.list.viewUrl && { +export const SubscribeButtons = (props: Props) => + <> + + + ; + +const PrimaryButton = (props: Props) => { const buttonProps = buildButtonProps(props.name, props.viewUrl); return ( - <> - - - + ) }; -const PrimaryButton = (props: [ButtonProps, boolean]) => - ; - const MirrorButtons = (props: Props) => <> {props.viewUrlMirrors && props.viewUrlMirrors.length - ? props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => { - const buttonProps = buildButtonProps(props.name, viewUrlMirror); - return - }) + ? props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => + + ) : null} ; +interface MirrorButtonProps { + index: number; + viewUrlMirror: string; + name: string; +} + +const MirrorButton = (props: MirrorButtonProps) => { + const buttonProps = buildButtonProps(props.name, props.viewUrlMirror); + return ( + + ) +} + const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => { let type: ButtonType = "primary"; let disabled: boolean = false; From 81a38e7a6237e981659ad8f99678a862104b8b0e Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 13:31:42 -0500 Subject: [PATCH 125/163] fix indent --- src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx index 48a91809e..553880c4c 100644 --- a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx +++ b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx @@ -22,7 +22,7 @@ const PrimaryButton = (props: Props) => { icon="import" {...buttonProps[0]}> Subscribe - + ) }; From aabfda9c9e983c52b0cbd268e5a408cdc315378b Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 13:55:09 -0500 Subject: [PATCH 126/163] convert ListInfoDrawer from class to function w/hooks --- .../src/components/ListInfoDrawer.tsx | 121 ++++++++---------- 1 file changed, 52 insertions(+), 69 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx index 54fe5df6f..68e76212e 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx @@ -1,6 +1,6 @@ import { Divider, Drawer } from 'antd'; import ButtonGroup from 'antd/lib/button/button-group'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { Language } from '../interfaces/Language'; @@ -21,108 +21,91 @@ interface Props { tags: Tag[]; }; -interface State { - baseDocumentTitle: string; -} +export const ListInfoDrawer = (props: RouteComponentProps & Props) => { + const [originalTitle] = useState(document.title); -export class ListInfoDrawer extends React.Component { - constructor(props: any) { - super(props); - this.state = { - baseDocumentTitle: document.title - }; - } + useEffect(() => { + const updateTitle = () => { + document.title = props.list.name + " | " + originalTitle; + } + updateTitle(); + return () => { document.title = originalTitle; } + }, [props.list, originalTitle]); - componentDidMount() { - this.updateTitle(); - } - - render() { - return this.props.history.push("/")}> - - {this.props.list.languageIds - ? + onClose={() => props.history.push("/")}> + + {props.list.languageIds + ? : null} - {this.props.list.tagIds - ? + {props.list.tagIds + ? : null} - {this.props.license - ? + {props.license + ? : null} - {this.props.list.publishedDate + {props.list.publishedDate ?

First Published Date:

- {new Date(this.props.list.publishedDate).toDateString()} + {new Date(props.list.publishedDate).toDateString()}
: null} - {this.props.list.viewUrl && } - {this.props.list.viewUrl && - } + {props.list.viewUrl && + } - {this.props.list.homeUrl && - } - {this.props.list.policyUrl && - } - {this.props.list.emailAddress && - } - {this.props.list.issuesUrl && - } - {this.props.list.submissionUrl && - } - {this.props.list.forumUrl && - } - {this.props.list.chatUrl && - } - {this.props.list.donateUrl && - }
- } - - componentDidUpdate() { - this.updateTitle(); - } - - private updateTitle() { - document.title = this.props.list.name + " | " + this.state.baseDocumentTitle; - } - - componentWillUnmount() { - document.title = this.state.baseDocumentTitle - } + ) } \ No newline at end of file From 2e7d435035ca6cbd4deb8a87fc4af91d4b56173b Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 16:32:07 -0500 Subject: [PATCH 127/163] rm trailing new lines --- src/FilterLists.Web.V2/src/App.test.tsx | 2 +- src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx | 2 +- src/FilterLists.Web.V2/src/components/index.ts | 2 +- src/FilterLists.Web.V2/src/components/languageCloud/index.ts | 2 +- src/FilterLists.Web.V2/src/components/tagCloud/index.ts | 2 +- src/FilterLists.Web.V2/src/hooks/index.ts | 2 +- src/FilterLists.Web.V2/src/hooks/useApiData.tsx | 2 +- src/FilterLists.Web.V2/src/hooks/useLanguages.tsx | 2 +- src/FilterLists.Web.V2/src/hooks/useLicenses.tsx | 2 +- src/FilterLists.Web.V2/src/hooks/useLists.tsx | 2 +- src/FilterLists.Web.V2/src/hooks/useTags.tsx | 2 +- src/FilterLists.Web.V2/src/react-app-env.d.ts | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.test.tsx b/src/FilterLists.Web.V2/src/App.test.tsx index 7ca229b98..7911e5b41 100644 --- a/src/FilterLists.Web.V2/src/App.test.tsx +++ b/src/FilterLists.Web.V2/src/App.test.tsx @@ -7,4 +7,4 @@ it('renders without crashing', () => { const div = document.createElement('div'); ReactDOM.render(, div); ReactDOM.unmountComponentAtNode(div); -}); +}); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx index 553880c4c..60a3897ee 100644 --- a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx +++ b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx @@ -88,4 +88,4 @@ const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`; return [{ type, href, title }, disabled] -} +} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/index.ts b/src/FilterLists.Web.V2/src/components/index.ts index 654f34a7d..2392fcc0e 100644 --- a/src/FilterLists.Web.V2/src/components/index.ts +++ b/src/FilterLists.Web.V2/src/components/index.ts @@ -1,3 +1,3 @@ import { ListsTable } from './listsTable'; -export { ListsTable }; +export { ListsTable }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/languageCloud/index.ts b/src/FilterLists.Web.V2/src/components/languageCloud/index.ts index 063a12c8e..3f61a4e3d 100644 --- a/src/FilterLists.Web.V2/src/components/languageCloud/index.ts +++ b/src/FilterLists.Web.V2/src/components/languageCloud/index.ts @@ -1,3 +1,3 @@ import { LanguageCloud } from './LanguageCloud'; -export { LanguageCloud }; +export { LanguageCloud }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/tagCloud/index.ts b/src/FilterLists.Web.V2/src/components/tagCloud/index.ts index 1e8216050..eeb9fca3f 100644 --- a/src/FilterLists.Web.V2/src/components/tagCloud/index.ts +++ b/src/FilterLists.Web.V2/src/components/tagCloud/index.ts @@ -1,3 +1,3 @@ import { TagCloud } from './TagCloud'; -export { TagCloud }; +export { TagCloud }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/index.ts b/src/FilterLists.Web.V2/src/hooks/index.ts index 22bef0416..b6f83f8e1 100644 --- a/src/FilterLists.Web.V2/src/hooks/index.ts +++ b/src/FilterLists.Web.V2/src/hooks/index.ts @@ -4,4 +4,4 @@ import { useLists } from './useLists'; import { useTablePageSizer } from './useTablePageSizer'; import { useTags } from './useTags'; -export { useLanguages, useLicenses, useLists, useTablePageSizer, useTags }; +export { useLanguages, useLicenses, useLists, useTablePageSizer, useTags }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useApiData.tsx b/src/FilterLists.Web.V2/src/hooks/useApiData.tsx index d58f5311b..81e2dba8d 100644 --- a/src/FilterLists.Web.V2/src/hooks/useApiData.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useApiData.tsx @@ -11,4 +11,4 @@ export const useApiData = (url: string) => { fetchData(); }, [url]); return data; -}; +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx b/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx index 8daaf0e95..862aee4cf 100644 --- a/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx @@ -1,4 +1,4 @@ import { Language } from '../interfaces/Language'; import { useApiData } from './useApiData'; -export const useLanguages = () => useApiData("/api/v1/languages") || []; +export const useLanguages = () => useApiData("/api/v1/languages") || []; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx b/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx index 026de972d..d11b6868c 100644 --- a/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx @@ -1,4 +1,4 @@ import { License } from '../interfaces/License'; import { useApiData } from './useApiData'; -export const useLicenses = () => useApiData("/api/v1/licenses") || []; +export const useLicenses = () => useApiData("/api/v1/licenses") || []; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useLists.tsx b/src/FilterLists.Web.V2/src/hooks/useLists.tsx index 18714105a..ede7f5f0b 100644 --- a/src/FilterLists.Web.V2/src/hooks/useLists.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useLists.tsx @@ -1,4 +1,4 @@ import { List } from '../interfaces/List'; import { useApiData } from './useApiData'; -export const useLists = () => useApiData("/api/v1/lists") || []; +export const useLists = () => useApiData("/api/v1/lists") || []; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useTags.tsx b/src/FilterLists.Web.V2/src/hooks/useTags.tsx index 2abebd2c5..1840726a4 100644 --- a/src/FilterLists.Web.V2/src/hooks/useTags.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useTags.tsx @@ -1,4 +1,4 @@ import { Tag } from '../interfaces/Tag'; import { useApiData } from './useApiData'; -export const useTags = () => useApiData("/api/v1/tags") || []; +export const useTags = () => useApiData("/api/v1/tags") || []; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/react-app-env.d.ts b/src/FilterLists.Web.V2/src/react-app-env.d.ts index 6431bc5fc..6889c6b37 100644 --- a/src/FilterLists.Web.V2/src/react-app-env.d.ts +++ b/src/FilterLists.Web.V2/src/react-app-env.d.ts @@ -1 +1 @@ -/// +/// \ No newline at end of file From 33ce3be72f4106bf3b8c238d656a3fe249545d8b Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 16:32:14 -0500 Subject: [PATCH 128/163] convert span to fragment --- src/FilterLists.Web.V2/src/App.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index c04abd8ce..e623a8f4e 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -39,13 +39,14 @@ const NotFound = (props: RouteComponentProps) => ; const CopyrightAuthor = () => - + <> ©{new Date().getFullYear()} 
- Collin M. Barrett - ; + Collin M. Barrett + + ; const Community = () => Date: Sat, 31 Aug 2019 16:40:01 -0500 Subject: [PATCH 129/163] tidy syntax --- .../src/hooks/useTablePageSizer.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx b/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx index cde7da212..419f568c6 100644 --- a/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx @@ -6,15 +6,13 @@ interface TablePageSize { } export const useTablePageSizer = () => { - const calculateSize = () => { - return { - pageSize: Math.floor((window.innerHeight - 211.5) / 56), - isNarrowWindow: window.innerWidth < 576 ? true : false - }; - } + const calculateSize = () => ({ + pageSize: Math.floor((window.innerHeight - 211.5) / 56), + isNarrowWindow: window.innerWidth < 576 ? true : false + }); const [state, setState] = useState(calculateSize()); useEffect(() => { - const updatePageSize = () => { setState(calculateSize()) } + const updatePageSize = () => setState(calculateSize()) window.addEventListener('resize', updatePageSize); return () => window.removeEventListener('resize', updatePageSize); }, []); From da549da826fb78a78dfc72961522b228ce30e6bf Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 17:13:07 -0500 Subject: [PATCH 130/163] minor linting --- src/FilterLists.Web.V2/.gitignore | 2 +- src/FilterLists.Web.V2/package-lock.json | Bin 562496 -> 562495 bytes src/FilterLists.Web.V2/package.json | 2 +- src/FilterLists.Web.V2/src/App.tsx | 8 +++--- .../src/components/LicenseTag.tsx | 4 ++- .../src/components/ListInfoButton.tsx | 18 ++++++------ .../src/components/ListInfoDrawer.tsx | 12 +++----- .../src/components/SubscribeButtons.tsx | 20 ++++++------- .../languageCloud/LanguageCloud.tsx | 4 +-- .../src/components/listsTable/ListDrawer.tsx | 8 +++--- .../src/components/listsTable/ListsTable.tsx | 6 ++-- .../components/listsTable/ListsTableHoc.tsx | 4 +-- .../src/components/listsTable/arraySorter.ts | 27 +++++++++--------- .../src/components/listsTable/index.ts | 2 +- .../src/components/tagCloud/TagCloud.tsx | 4 +-- .../src/hooks/useApiData.tsx | 3 +- .../src/hooks/useTablePageSizer.tsx | 15 +++++----- src/FilterLists.Web.V2/src/utils/index.ts | 2 +- 18 files changed, 71 insertions(+), 70 deletions(-) diff --git a/src/FilterLists.Web.V2/.gitignore b/src/FilterLists.Web.V2/.gitignore index 4d29575de..24cdedf82 100644 --- a/src/FilterLists.Web.V2/.gitignore +++ b/src/FilterLists.Web.V2/.gitignore @@ -20,4 +20,4 @@ npm-debug.log* yarn-debug.log* -yarn-error.log* +yarn-error.log* \ No newline at end of file diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json index f454712090df464cdf087440fe52dde3aaad7fd8..316000e1ff14c3101af1bdcc883afb7cc1a14eaf 100644 GIT binary patch delta 25 gcmX@GN@@QprG^&97N!>F7M2#)7Pc1lEgbe!0f3?i-~a#s delta 27 icmdnLO6kBVrG^&97N!>F7M2#)7Pc1lEgbe!8My$GYY6KA diff --git a/src/FilterLists.Web.V2/package.json b/src/FilterLists.Web.V2/package.json index b9d130dda..ad140b771 100644 --- a/src/FilterLists.Web.V2/package.json +++ b/src/FilterLists.Web.V2/package.json @@ -39,4 +39,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx index e623a8f4e..c56bff830 100644 --- a/src/FilterLists.Web.V2/src/App.tsx +++ b/src/FilterLists.Web.V2/src/App.tsx @@ -53,25 +53,25 @@ const Community = () => title="FilterLists Discourse community forum" target="_blank" rel="noopener noreferrer"> Community - ; + ; const GitHub = () => GitHub - ; + ; const Api = () => API - ; + ; const Donate = () => Donate - ; \ No newline at end of file + ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx index 80a527e07..cd4a939ff 100644 --- a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx +++ b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx @@ -23,4 +23,6 @@ const TagContents = (props: Props) => ? {props.license.name} - : {props.license.name} \ No newline at end of file + : <> + {props.license.name} + ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx index d17d0a21c..13d0abd51 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx @@ -10,12 +10,14 @@ interface Props { export const ListInfoButton = (props: RouteComponentProps & Props) => { const listPath = `/lists/${props.list.id}`; - return + return ( + + ); }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx index 68e76212e..0aebf639e 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx @@ -23,15 +23,11 @@ interface Props { export const ListInfoDrawer = (props: RouteComponentProps & Props) => { const [originalTitle] = useState(document.title); - useEffect(() => { - const updateTitle = () => { - document.title = props.list.name + " | " + originalTitle; - } + const updateTitle = () => document.title = props.list.name + " | " + originalTitle; updateTitle(); - return () => { document.title = originalTitle; } + return () => { document.title = originalTitle; }; }, [props.list, originalTitle]); - return ( { icon="dollar" />} - ) -} \ No newline at end of file + ); +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx index 60a3897ee..c0a5eac18 100644 --- a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx +++ b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx @@ -23,7 +23,7 @@ const PrimaryButton = (props: Props) => { {...buttonProps[0]}> Subscribe - ) + ); }; const MirrorButtons = (props: Props) => @@ -39,7 +39,7 @@ interface MirrorButtonProps { index: number; viewUrlMirror: string; name: string; -} +}; const MirrorButton = (props: MirrorButtonProps) => { const buttonProps = buildButtonProps(props.name, props.viewUrlMirror); @@ -52,8 +52,8 @@ const MirrorButton = (props: MirrorButtonProps) => { {...buttonProps[0]}> {`Subscribe (Mirror ${props.index + 1})`} - ) -} + ); +}; const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => { let type: ButtonType = "primary"; @@ -70,22 +70,22 @@ const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] if (viewUrl.includes(".onion/")) { type = "dashed"; prefixes.push("TOR"); - } + }; if (viewUrl.includes("http://")) { type = "danger"; prefixes.push("INSECURE"); - } + }; // Software protocols if (viewUrl.includes(".tpl")) { disabled = true; // IE not supported by FilterLists - } + }; if (viewUrl.includes(".lsrules") || viewUrl.includes("?hostformat=littlesnitch")) { href = `x-littlesnitch:subscribe-rules?url=${hrefLocation}`; message = `Subscribe to ${name} with Little Snitch's rule group subscription feature.`; - } + }; const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`; - return [{ type, href, title }, disabled] -} \ No newline at end of file + return [{ type, href, title }, disabled]; +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx b/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx index 36781bce1..4c64ca1e2 100644 --- a/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx +++ b/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx @@ -5,8 +5,8 @@ import { Language } from '../../interfaces/Language'; import styles from './LanguageCloud.module.css'; interface Props { - languages: Language[] - showLabel?: boolean + languages: Language[]; + showLabel?: boolean; }; export const LanguageCloud = (props: Props) => diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx index c71162dbc..67a53b176 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx @@ -12,7 +12,7 @@ interface Props { languages: Language[]; licenses: License[]; tags: Tag[]; -} +}; export const ListDrawer = (props: Props) => { const renderDrawer = (rp: RouteComponentProps) => { @@ -24,7 +24,7 @@ export const ListDrawer = (props: Props) => { license={list.licenseId ? props.licenses.find((l: License) => list.licenseId === l.id) : undefined} tags={list.tagIds && props.tags.filter((t: Tag) => list.tagIds.includes(t.id))} {...rp} /> - : props.lists && props.lists.length && + : props.lists && props.lists.length && ; }; - return -} \ No newline at end of file + return ; +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index 37ad94a76..0e2db3d73 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -20,7 +20,7 @@ interface Props { languages: Language[]; licenses: License[]; tags: Tag[]; -} +}; export const ListsTable = (props: RouteComponentProps & Props) => { const tablePageSize = useTablePageSizer(); @@ -80,5 +80,5 @@ export const ListsTable = (props: RouteComponentProps & Props) => { className={styles.nogrow} render={(tagIds: number[]) => tagIds ? tagIds.includes(t.id))} /> : null} />} - ) -} \ No newline at end of file + ); +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx index 8884df941..690927159 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx @@ -15,5 +15,5 @@ export const ListsTableHoc = (props: RouteComponentProps) => { - ) -} \ No newline at end of file + ); +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts b/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts index f6dfb8aee..60dc733a2 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts +++ b/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts @@ -1,17 +1,18 @@ interface ArraySortableEntity { id: number; name: string; -} +}; -export const arraySorter = (a: number[], b: number[], entities: ArraySortableEntity[]): number => a && a.length - ? b && b.length - ? a.length === b.length - ? entities.filter((e: ArraySortableEntity) => a.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() - > entities.filter((e: ArraySortableEntity) => b.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() - ? 1 - : -1 - : a.length > b.length - ? -1 - : 1 - : -1 - : 1; \ No newline at end of file +export const arraySorter = (a: number[], b: number[], entities: ArraySortableEntity[]) => + a && a.length + ? b && b.length + ? a.length === b.length + ? entities.filter((e: ArraySortableEntity) => a.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() + > entities.filter((e: ArraySortableEntity) => b.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() + ? 1 + : -1 + : a.length > b.length + ? -1 + : 1 + : -1 + : 1; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listsTable/index.ts b/src/FilterLists.Web.V2/src/components/listsTable/index.ts index 595fade9b..e69706c2e 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/index.ts +++ b/src/FilterLists.Web.V2/src/components/listsTable/index.ts @@ -1,3 +1,3 @@ import { ListsTableHoc } from './ListsTableHoc'; -export { ListsTableHoc as ListsTable } \ No newline at end of file +export { ListsTableHoc as ListsTable }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx b/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx index 38525cf89..45b0d4073 100644 --- a/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx +++ b/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx @@ -5,8 +5,8 @@ import { Tag as TagInterface } from '../../interfaces/Tag'; import styles from './TagCloud.module.css'; interface Props { - tags: TagInterface[] - showLabel?: boolean + tags: TagInterface[]; + showLabel?: boolean; }; export const TagCloud = (props: Props) => diff --git a/src/FilterLists.Web.V2/src/hooks/useApiData.tsx b/src/FilterLists.Web.V2/src/hooks/useApiData.tsx index 81e2dba8d..14522fa90 100644 --- a/src/FilterLists.Web.V2/src/hooks/useApiData.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useApiData.tsx @@ -3,11 +3,10 @@ import { useEffect, useState } from 'react'; export const useApiData = (url: string) => { const [data, setData] = useState(); useEffect(() => { - const fetchData = async () => { + const fetchData = async () => (await fetch(url)) .json() .then(r => setData(r)); - }; fetchData(); }, [url]); return data; diff --git a/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx b/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx index 419f568c6..979cf8258 100644 --- a/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx @@ -3,18 +3,19 @@ import { useEffect, useState } from 'react'; interface TablePageSize { pageSize: number; isNarrowWindow: boolean; -} +}; export const useTablePageSizer = () => { - const calculateSize = () => ({ - pageSize: Math.floor((window.innerHeight - 211.5) / 56), - isNarrowWindow: window.innerWidth < 576 ? true : false - }); const [state, setState] = useState(calculateSize()); useEffect(() => { - const updatePageSize = () => setState(calculateSize()) + const updatePageSize = () => setState(calculateSize()); window.addEventListener('resize', updatePageSize); return () => window.removeEventListener('resize', updatePageSize); }, []); return state; -} \ No newline at end of file +}; + +const calculateSize = () => ({ + pageSize: Math.floor((window.innerHeight - 211.5) / 56), + isNarrowWindow: window.innerWidth < 576 ? true : false +}); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/utils/index.ts b/src/FilterLists.Web.V2/src/utils/index.ts index 61acd744c..d22b49973 100644 --- a/src/FilterLists.Web.V2/src/utils/index.ts +++ b/src/FilterLists.Web.V2/src/utils/index.ts @@ -1,3 +1,3 @@ import { nameof } from './nameof'; -export { nameof } \ No newline at end of file +export { nameof }; \ No newline at end of file From ea43859a5266c5e9b9ac734184c1084b77b021ce Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 17:20:36 -0500 Subject: [PATCH 131/163] inline lint --- src/FilterLists.Web.V2/src/hooks/useApiData.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/hooks/useApiData.tsx b/src/FilterLists.Web.V2/src/hooks/useApiData.tsx index 14522fa90..4813771bc 100644 --- a/src/FilterLists.Web.V2/src/hooks/useApiData.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useApiData.tsx @@ -3,10 +3,7 @@ import { useEffect, useState } from 'react'; export const useApiData = (url: string) => { const [data, setData] = useState(); useEffect(() => { - const fetchData = async () => - (await fetch(url)) - .json() - .then(r => setData(r)); + const fetchData = async () => (await fetch(url)).json().then(r => setData(r)); fetchData(); }, [url]); return data; From 3f5c9f81e8f91fb74771b505307be712750292a9 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 17:22:44 -0500 Subject: [PATCH 132/163] fix unique key on mirror subscribe buttons --- src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx index c0a5eac18..e544a68b7 100644 --- a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx +++ b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx @@ -30,7 +30,7 @@ const MirrorButtons = (props: Props) => <> {props.viewUrlMirrors && props.viewUrlMirrors.length ? props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - + ) : null} ; @@ -45,7 +45,6 @@ const MirrorButton = (props: MirrorButtonProps) => { const buttonProps = buildButtonProps(props.name, props.viewUrlMirror); return ( ); }; -const MirrorButtons = (props: Props) => +interface MirrorButtonsProps { + name: string; + viewUrlMirrors: string[]; +}; + +const MirrorButtons = (props: MirrorButtonsProps) => <> {props.viewUrlMirrors && props.viewUrlMirrors.length ? props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - - ) + ) : null} ; @@ -45,16 +57,18 @@ const MirrorButton = (props: MirrorButtonProps) => { const buttonProps = buildButtonProps(props.name, props.viewUrlMirror); return ( ); }; -const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] => { +const buildButtonProps = (name: string, viewUrl: string) => { let type: ButtonType = "primary"; let disabled: boolean = false; @@ -86,5 +100,5 @@ const buildButtonProps = (name: string, viewUrl: string): [ButtonProps, boolean] const title = `${prefixes.length ? prefixes.join(" | ") + " | " : ""}${message}`; - return [{ type, href, title }, disabled]; + return { disabled, type, href, title }; }; \ No newline at end of file From e9f233bb2bc1fdf160f8cfa0fc526807639bb157 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 31 Aug 2019 20:32:33 -0500 Subject: [PATCH 134/163] rm lists from list url path --- src/FilterLists.Web.V2/src/components/ListInfoButton.tsx | 2 +- src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx index 13d0abd51..9d49bd744 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx @@ -9,7 +9,7 @@ interface Props { }; export const ListInfoButton = (props: RouteComponentProps & Props) => { - const listPath = `/lists/${props.list.id}`; + const listPath = `/${props.list.id}`; return (
- | | | | + | | | | |
; @@ -48,30 +48,37 @@ const CopyrightAuthor = () => ; +const Twitter = () => + + Twitter + ; + const Community = () => - Community + Community ; const GitHub = () => - GitHub + GitHub ; const Api = () => - API + API ; const Donate = () => - Donate + Donate ; \ No newline at end of file From 9074bff5422778f0761ae6346e00d0cd586b3145 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 1 Sep 2019 09:40:25 -0500 Subject: [PATCH 137/163] mv list urls back under lists path for more url flexibility --- src/FilterLists.Web.V2/src/components/ListInfoButton.tsx | 2 +- src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx index cfc6f11d7..9dc45da48 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx @@ -10,7 +10,7 @@ interface Props { }; export const ListInfoButton = (props: RouteComponentProps & Props) => { - const listPath = `/${slugify(props.list.name)}`; + const listPath = `/lists/${slugify(props.list.name)}`; return ( - ); -}; - interface MirrorButtonsProps { name: string; viewUrlMirrors: string[]; @@ -43,18 +23,18 @@ const MirrorButtons = (props: MirrorButtonsProps) => <> {props.viewUrlMirrors && props.viewUrlMirrors.length ? props.viewUrlMirrors.map((viewUrlMirror: string, i: number) => - ) + ) : null} ; -interface MirrorButtonProps { - index: number; - viewUrlMirror: string; +interface SubscribeButtonProps { name: string; + viewUrl: string; + text: string; }; -const MirrorButton = (props: MirrorButtonProps) => { - const buttonProps = buildButtonProps(props.name, props.viewUrlMirror); +const SubscribeButton = (props: SubscribeButtonProps) => { + const buttonProps = buildButtonProps(props.name, props.viewUrl); return ( ); }; From 1727c168c6f7329f3fb67aa694e0ed815c3b8d14 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 1 Sep 2019 16:01:13 -0500 Subject: [PATCH 144/163] handle null check within component --- .../src/components/SubscribeButtons.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx index ae00708bc..fd2bd453e 100644 --- a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx +++ b/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx @@ -9,10 +9,12 @@ interface Props { }; export const SubscribeButtons = (props: Props) => - <> - - - ; + props.viewUrl + ? <> + + + + : null; interface MirrorButtonsProps { name: string; From 3cb2c457039a04794d38beb3a0dfc4242a37bdaf Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sun, 1 Sep 2019 16:57:08 -0500 Subject: [PATCH 145/163] extract PublishedDate, misc. linting --- .../src/components/LicenseTag.tsx | 29 ++-- .../src/components/LinkButton.tsx | 22 +-- .../src/components/ListInfoButton.tsx | 8 +- .../src/components/ListInfoDrawer.tsx | 136 +++++++++--------- .../src/components/PublishedDate.tsx | 14 ++ .../src/components/SubscribeButtons.tsx | 15 +- .../src/components/listsTable/ListDrawer.tsx | 2 +- .../src/components/listsTable/ListsTable.tsx | 2 +- .../components/listsTable/ListsTableHoc.tsx | 15 +- 9 files changed, 143 insertions(+), 100 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/components/PublishedDate.tsx diff --git a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx index cd4a939ff..4f1c1b8f1 100644 --- a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx +++ b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx @@ -1,28 +1,33 @@ import { Tag } from 'antd'; import * as React from 'react'; -import { License } from '../interfaces/License'; - interface Props { - license: License; + name: string; + descriptionUrl: string; showLabel?: boolean }; export const LicenseTag = (props: Props) => - props.license && props.license.name - ?
+ props.name + ? <> {props.showLabel &&

License:

} - + -
+ : null; -const TagContents = (props: Props) => - props.license.descriptionUrl - ?
- {props.license.name} +interface TagContentsProps { + name: string; + descriptionUrl: string; +}; + +const TagContents = (props: TagContentsProps) => + props.descriptionUrl + ? + {props.name} : <> - {props.license.name} + {props.name} ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/LinkButton.tsx b/src/FilterLists.Web.V2/src/components/LinkButton.tsx index 94d4da593..49f79c86c 100644 --- a/src/FilterLists.Web.V2/src/components/LinkButton.tsx +++ b/src/FilterLists.Web.V2/src/components/LinkButton.tsx @@ -11,13 +11,15 @@ interface Props { }; export const LinkButton = (props: Props) => - ; \ No newline at end of file + props.url && props.text + ? + : null; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx index 9dc45da48..041a79b06 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx @@ -3,18 +3,16 @@ import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; import slugify from 'slugify'; -import { List } from '../interfaces/List'; - interface Props { - list: List; + listName: string; }; export const ListInfoButton = (props: RouteComponentProps & Props) => { - const listPath = `/lists/${slugify(props.list.name)}`; + const listPath = `/lists/${slugify(props.listName)}`; return ( : null; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx index 4a7e36c26..b9c175abf 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx @@ -51,15 +51,12 @@ export const ListInfoDrawer = (props: RouteComponentProps & Props) => { tags={props.tags} showLabel={true} /> + name={props.license && props.license.name} + descriptionUrl={props.license.descriptionUrl} /> - + props.publishedDate ? <> - {props.showLabel &&

First Published Date:

} +

First Published Date:

{new Date(props.publishedDate).toDateString()} : null; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index c3b6bf2f0..07b5e09c9 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -34,14 +34,20 @@ export const ListsTable = (props: RouteComponentProps & Props) => { rowKey={record => record.id.toString()} loading={lists.length ? false : true} size="small" - pagination={{ size: "small", simple: true, style: { float: "left" }, pageSize: tablePageSize.pageSize }} + pagination={{ + size: "small", + simple: true, + style: { float: "left" }, + pageSize: tablePageSize.pageSize + }} scroll={{ x: tablePageSize.isNarrowWindow ? undefined : 1200 }}> title="Info" dataIndex={nameof("id")} className={styles.nogrow} fixed="left" - render={(_text: string, record: List) => } /> + render={(_id: number, list: List) => + } /> title="Name" dataIndex={nameof("name")} @@ -50,14 +56,18 @@ export const ListsTable = (props: RouteComponentProps & Props) => { width={tablePageSize.isNarrowWindow ? undefined : 200} className={styles.nogrow} fixed="left" - render={(text: string) =>
{text}
} /> + render={(name: string) => +
{name}
} /> {tablePageSize.isNarrowWindow ? null : title="Description" dataIndex={nameof("description")} className={styles.nogrow} - render={(_text: string, record: List) => } />} + render={(description: string, list: List) => + } />} {tablePageSize.isNarrowWindow ? null : @@ -65,13 +75,14 @@ export const ListsTable = (props: RouteComponentProps & Props) => { dataIndex={nameof("syntaxId")} sorter={(a, b) => { const getSoftwareIds = (l: List) => software.filter((s: Software) => s.syntaxIds.includes(l.syntaxId)).map(s => s.id); - const aSoftwareIds = getSoftwareIds(a); - const bSoftwareIds = getSoftwareIds(b); - return arraySorter(aSoftwareIds, bSoftwareIds, software); + return arraySorter(getSoftwareIds(a), getSoftwareIds(b), software); }} width={143} className={styles.nogrow} - render={(syntaxId: number) => syntaxId ? s.syntaxIds.includes(syntaxId))} /> : null} />} + render={(syntaxId: number) => + syntaxId + ? s.syntaxIds.includes(syntaxId))} /> + : null} />} {tablePageSize.isNarrowWindow ? null : @@ -80,7 +91,10 @@ export const ListsTable = (props: RouteComponentProps & Props) => { sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, languages)} width={125} className={styles.nogrow} - render={(languageIds: number[]) => languageIds ? languageIds.includes(l.id))} /> : null} />} + render={(languageIds: number[]) => + languageIds + ? languageIds.includes(l.id))} /> + : null} />} {tablePageSize.isNarrowWindow ? null : @@ -89,7 +103,10 @@ export const ListsTable = (props: RouteComponentProps & Props) => { sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, tags)} width={275} className={styles.nogrow} - render={(tagIds: number[]) => tagIds ? tagIds.includes(t.id))} /> : null} />} + render={(tagIds: number[]) => + tagIds + ? tagIds.includes(t.id))} /> + : null} />} ); }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts b/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts index 60dc733a2..e438c34b9 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts +++ b/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts @@ -7,8 +7,8 @@ export const arraySorter = (a: number[], b: number[], entities: ArraySortableEnt a && a.length ? b && b.length ? a.length === b.length - ? entities.filter((e: ArraySortableEntity) => a.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() - > entities.filter((e: ArraySortableEntity) => b.indexOf(e.id) > -1).map((e: ArraySortableEntity) => e.name).join().toLowerCase() + ? entities.filter((e: ArraySortableEntity) => a.includes(e.id)).map((e: ArraySortableEntity) => e.name).join().toLowerCase() + > entities.filter((e: ArraySortableEntity) => b.includes(e.id)).map((e: ArraySortableEntity) => e.name).join().toLowerCase() ? 1 : -1 : a.length > b.length diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareCloud.tsx b/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareCloud.tsx index df58c70ec..50090622d 100644 --- a/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareCloud.tsx +++ b/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareCloud.tsx @@ -15,10 +15,10 @@ export const SoftwareCloud = (props: Props) => {props.showLabel &&

{`Software:`}

} {props.software.map((s: Software, i: number) => s.homeUrl - ? + target="_blank" + rel="noopener noreferrer"> : )} From 1357adac4dd21ab477442b7c4772d1a27c67428b Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 09:10:36 -0500 Subject: [PATCH 151/163] fix link to icon --- src/FilterLists.Web.V2/public/index.html | 63 +++++++++++++-------- src/FilterLists.Web.V2/public/manifest.json | 2 +- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/FilterLists.Web.V2/public/index.html b/src/FilterLists.Web.V2/public/index.html index 4fedac461..ec85e765d 100644 --- a/src/FilterLists.Web.V2/public/index.html +++ b/src/FilterLists.Web.V2/public/index.html @@ -1,27 +1,42 @@ + + + + + + + + FilterLists | Subscriptions for uBlock Origin, Adblock Plus, AdGuard, ... + + + + + - - - - - - - FilterLists | Subscriptions for uBlock Origin, Adblock Plus, AdGuard, ... - - - - - - - -
-

FilterLists is built with ReactJS and therefore requires first-party JavaScript to be enabled. We do not use any - third-party JavaScript, and your privacy is very important to us. If you prefer not to enable JavaScript or your - browser does not support it, the data is also available on our GitHub repo.

-
- - - \ No newline at end of file + + +
+

+ FilterLists is built with ReactJS and therefore requires first-party + JavaScript to be enabled. We do not use any third-party JavaScript, and + your privacy is very important to us. If you prefer not to enable + JavaScript or your browser does not support it, the data is also + available on + our GitHub repo. +

+
+ + diff --git a/src/FilterLists.Web.V2/public/manifest.json b/src/FilterLists.Web.V2/public/manifest.json index 452af93c5..143de534b 100644 --- a/src/FilterLists.Web.V2/public/manifest.json +++ b/src/FilterLists.Web.V2/public/manifest.json @@ -12,4 +12,4 @@ "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" -} +} \ No newline at end of file From ac6ff94083b8688a1accda2d024106cab2c19bf5 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 09:10:44 -0500 Subject: [PATCH 152/163] fix undefined reference error --- src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx index b9c175abf..ba34aba97 100644 --- a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx @@ -52,7 +52,7 @@ export const ListInfoDrawer = (props: RouteComponentProps & Props) => { showLabel={true} /> + descriptionUrl={props.license && props.license.descriptionUrl} /> From 82ed18d51d40abc9f3bc4b3faf45fba5eb8a06da Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 10:07:35 -0500 Subject: [PATCH 153/163] add Syntax to drawer --- .../src/components/LicenseTag.tsx | 7 +---- .../src/components/ListInfoDrawer.tsx | 16 +++++++--- .../src/components/SyntaxTag.tsx | 30 +++++++++++++++++++ .../src/components/listsTable/ListDrawer.tsx | 5 +++- .../components/listsTable/ListsTableHoc.tsx | 4 ++- src/FilterLists.Web.V2/src/hooks/index.ts | 11 ++++++- .../src/hooks/useSyntaxes.tsx | 4 +++ .../src/interfaces/Syntax.ts | 7 +++++ 8 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 src/FilterLists.Web.V2/src/components/SyntaxTag.tsx create mode 100644 src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx create mode 100644 src/FilterLists.Web.V2/src/interfaces/Syntax.ts diff --git a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx index ff752dbaa..c96f25892 100644 --- a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx +++ b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx @@ -18,12 +18,7 @@ export const LicenseTag = (props: Props) => : null; -interface TagContentsProps { - name: string; - descriptionUrl: string; -}; - -const TagContents = (props: TagContentsProps) => +const TagContents = (props: Props) => props.descriptionUrl ? { - + {props.license && + } + {props.syntax && + } diff --git a/src/FilterLists.Web.V2/src/components/SyntaxTag.tsx b/src/FilterLists.Web.V2/src/components/SyntaxTag.tsx new file mode 100644 index 000000000..ccf9d174c --- /dev/null +++ b/src/FilterLists.Web.V2/src/components/SyntaxTag.tsx @@ -0,0 +1,30 @@ +import { Tag } from 'antd'; +import * as React from 'react'; + +interface Props { + name: string; + definitionUrl: string; +}; + +export const SyntaxTag = (props: Props) => + props.name + ? <> +

Syntax:

+ + + + + : null; + +const TagContents = (props: Props) => + props.definitionUrl + ?
+ {props.name} + + : <> + {props.name} + ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx index 81a3224e8..3cb1ae641 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx @@ -5,6 +5,7 @@ import { Language } from '../../interfaces/Language'; import { License } from '../../interfaces/License'; import { List } from '../../interfaces/List'; import { Software } from '../../interfaces/Software'; +import { Syntax } from '../../interfaces/Syntax'; import { Tag } from '../../interfaces/Tag'; import { ListInfoDrawer } from '../ListInfoDrawer'; @@ -13,6 +14,7 @@ interface Props { languages: Language[]; licenses: License[]; software: Software[]; + syntaxes: Syntax[]; tags: Tag[]; }; @@ -23,8 +25,9 @@ export const ListDrawer = (props: Props) => { ? list.languageIds.includes(l.id))} - license={(list.licenseId ? props.licenses.find((l: License) => list.licenseId === l.id) : props.licenses.find((l: License) => l.id === 5)) as License} + license={list.licenseId ? props.licenses.find((l: License) => list.licenseId === l.id) : props.licenses.find((l: License) => l.id === 5)} software={list.syntaxId ? props.software.filter((s: Software) => s.syntaxIds.includes(list.syntaxId)) : []} + syntax={list.syntaxId ? props.syntaxes.find(s => s.id === list.syntaxId) : undefined} tags={list.tagIds && props.tags.filter((t: Tag) => list.tagIds.includes(t.id))} {...rp} /> : (props.lists && props.lists.length && ) || null; diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx index e176c2c1e..1c0c39481 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; -import { useLanguages, useLicenses, useLists, useSoftware, useTags } from '../../hooks'; +import { useLanguages, useLicenses, useLists, useSoftware, useSyntaxes, useTags } from '../../hooks'; import { ListDrawer } from './ListDrawer'; import { ListsTable } from './ListsTable'; @@ -10,6 +10,7 @@ export const ListsTableHoc = (props: RouteComponentProps) => { const languages = useLanguages(); const licenses = useLicenses(); const software = useSoftware(); + const syntaxes = useSyntaxes(); const tags = useTags(); return ( <> @@ -25,6 +26,7 @@ export const ListsTableHoc = (props: RouteComponentProps) => { languages={languages} licenses={licenses} software={software} + syntaxes={syntaxes} tags={tags} /> ); diff --git a/src/FilterLists.Web.V2/src/hooks/index.ts b/src/FilterLists.Web.V2/src/hooks/index.ts index 019cb850b..97fc591b9 100644 --- a/src/FilterLists.Web.V2/src/hooks/index.ts +++ b/src/FilterLists.Web.V2/src/hooks/index.ts @@ -2,7 +2,16 @@ import { useLanguages } from './useLanguages'; import { useLicenses } from './useLicenses'; import { useLists } from './useLists'; import { useSoftware } from './useSoftware'; +import { useSyntaxes } from './useSyntaxes'; import { useTablePageSizer } from './useTablePageSizer'; import { useTags } from './useTags'; -export { useLanguages, useLicenses, useLists, useSoftware, useTablePageSizer, useTags }; \ No newline at end of file +export { + useLanguages, + useLicenses, + useLists, + useSoftware, + useSyntaxes, + useTablePageSizer, + useTags +}; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx b/src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx new file mode 100644 index 000000000..24415f461 --- /dev/null +++ b/src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx @@ -0,0 +1,4 @@ +import { Syntax } from '../interfaces/Syntax'; +import { useApiData } from './useApiData'; + +export const useSyntaxes = () => useApiData("/api/v1/syntaxes") || []; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/interfaces/Syntax.ts b/src/FilterLists.Web.V2/src/interfaces/Syntax.ts new file mode 100644 index 000000000..c2eea02d4 --- /dev/null +++ b/src/FilterLists.Web.V2/src/interfaces/Syntax.ts @@ -0,0 +1,7 @@ +export interface Syntax { + id: number; + definitionUrl: string; + filterListIds: number[]; + name: string; + softwareIds: number[]; +}; \ No newline at end of file From e33e2f16fae00bb299cdb771fdd6d2b3acedc94b Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 10:12:27 -0500 Subject: [PATCH 154/163] add/improve link titles --- src/FilterLists.Web.V2/src/components/LicenseTag.tsx | 1 + src/FilterLists.Web.V2/src/components/SyntaxTag.tsx | 1 + .../src/components/softwareCloud/SoftwareIcon.tsx | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx index c96f25892..d6349d4a5 100644 --- a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx +++ b/src/FilterLists.Web.V2/src/components/LicenseTag.tsx @@ -21,6 +21,7 @@ export const LicenseTag = (props: Props) => const TagContents = (props: Props) => props.descriptionUrl ? {props.name} diff --git a/src/FilterLists.Web.V2/src/components/SyntaxTag.tsx b/src/FilterLists.Web.V2/src/components/SyntaxTag.tsx index ccf9d174c..be50e6412 100644 --- a/src/FilterLists.Web.V2/src/components/SyntaxTag.tsx +++ b/src/FilterLists.Web.V2/src/components/SyntaxTag.tsx @@ -21,6 +21,7 @@ export const SyntaxTag = (props: Props) => const TagContents = (props: Props) => props.definitionUrl ? {props.name} diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareIcon.tsx b/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareIcon.tsx index b79cd9890..55057f058 100644 --- a/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareIcon.tsx +++ b/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareIcon.tsx @@ -46,7 +46,7 @@ export const SoftwareIcon = (props: Props) => src={icons[props.id].image} height="20" alt={icons[props.id].imageTitle} - title={icons[props.id].imageTitle} /> + title={`View ${icons[props.id].imageTitle}'s homepage.`} /> : null; interface Icon { From f1913fa6e2456ae1f0ac30139e1e1da13eabfb6c Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 11:34:55 -0500 Subject: [PATCH 155/163] implement free-form search on name and description columns --- .../src/components/listsTable/ListsTable.tsx | 10 ++- src/FilterLists.Web.V2/src/hooks/index.ts | 2 + .../src/hooks/useSearchColumnFilter.tsx | 62 +++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index 07b5e09c9..538a37129 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -2,7 +2,7 @@ import { Table } from 'antd'; import React from 'react'; import { RouteComponentProps } from 'react-router'; -import { useTablePageSizer } from '../../hooks'; +import { useSearchColumnFilter, useTablePageSizer } from '../../hooks'; import { Language } from '../../interfaces/Language'; import { License } from '../../interfaces/License'; import { List } from '../../interfaces/List'; @@ -28,6 +28,8 @@ interface Props { export const ListsTable = (props: RouteComponentProps & Props) => { const { lists, languages, licenses, software, tags, ...routeComponentProps } = props; const tablePageSize = useTablePageSizer(); + const searchNameColumn = useSearchColumnFilter(nameof("name")); + const searchDescriptionColumn = useSearchColumnFilter(nameof("description")); return ( dataSource={lists} @@ -56,6 +58,9 @@ export const ListsTable = (props: RouteComponentProps & Props) => { width={tablePageSize.isNarrowWindow ? undefined : 200} className={styles.nogrow} fixed="left" + filterDropdown={searchNameColumn.filterDropdown} + filterIcon={searchNameColumn.filterIcon} + onFilter={searchNameColumn.onFilter} render={(name: string) =>
{name}
} /> {tablePageSize.isNarrowWindow @@ -64,6 +69,9 @@ export const ListsTable = (props: RouteComponentProps & Props) => { title="Description" dataIndex={nameof("description")} className={styles.nogrow} + filterDropdown={searchDescriptionColumn.filterDropdown} + filterIcon={searchDescriptionColumn.filterIcon} + onFilter={searchDescriptionColumn.onFilter} render={(description: string, list: List) => { + filterDropdown?: React.ReactNode | ((props: FilterDropdownProps) => React.ReactNode); + filterIcon?: React.ReactNode | ((filtered: boolean) => React.ReactNode); + onFilter?: (value: any, record: T) => boolean; +} + +export const useSearchColumnFilter = (dataIndex: string) => { + const [filterProps, setFilterProps] = useState>({ + filterDropdown: undefined, + filterIcon: undefined, + onFilter: undefined + }); + useEffect(() => { + const handleSearch = (confirm?: () => void) => { + confirm && confirm(); + }; + const handleReset = (clearFilters?: (selectedKeys: string[]) => void) => { + clearFilters && clearFilters([]); + }; + setFilterProps({ + filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => ( +
+ setSelectedKeys && setSelectedKeys(e.target.value ? [e.target.value] : [])} + onPressEnter={() => handleSearch(confirm)} + style={{ width: 188, marginBottom: 8, display: 'block' }} /> + + +
+ ), + filterIcon: filtered => ( + + ), + onFilter: (value, record) => { + const searchValue = (record as any)[dataIndex]; + return searchValue && searchValue + .toString() + .toLowerCase() + .includes(value.toLowerCase()) + } + }) + }, [dataIndex]); + return filterProps; +}; \ No newline at end of file From 9fa91ffaa660f2bfd0b196a6b8176ca9bb2932be Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 11:40:59 -0500 Subject: [PATCH 156/163] value.toString() --- src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx b/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx index 66c2eb4b6..30c2aa2a4 100644 --- a/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx @@ -51,10 +51,7 @@ export const useSearchColumnFilter = (dataIndex: string) => { ), onFilter: (value, record) => { const searchValue = (record as any)[dataIndex]; - return searchValue && searchValue - .toString() - .toLowerCase() - .includes(value.toLowerCase()) + return searchValue && searchValue.toString().toLowerCase().includes(value.toString().toLowerCase()) } }) }, [dataIndex]); From 39c979625a3ed7933f3ef784d966de6121465ec7 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 11:46:37 -0500 Subject: [PATCH 157/163] capitalize placeholder --- .../src/hooks/useSearchColumnFilter.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx b/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx index 30c2aa2a4..e0a3c8480 100644 --- a/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx @@ -25,7 +25,7 @@ export const useSearchColumnFilter = (dataIndex: string) => { filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
setSelectedKeys && setSelectedKeys(e.target.value ? [e.target.value] : [])} onPressEnter={() => handleSearch(confirm)} @@ -35,20 +35,18 @@ export const useSearchColumnFilter = (dataIndex: string) => { onClick={() => handleSearch(confirm)} icon="search" size="small" - style={{ width: 90, marginRight: 8 }} > + style={{ width: 90, marginRight: 8 }} > Search
), - filterIcon: filtered => ( - - ), + filterIcon: filtered => , onFilter: (value, record) => { const searchValue = (record as any)[dataIndex]; return searchValue && searchValue.toString().toLowerCase().includes(value.toString().toLowerCase()) From a1bcdaf4cf35cd29832a8a9aebabe1f80950913d Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 12:48:17 -0500 Subject: [PATCH 158/163] add Software column filter, sort all entities in hooks --- .../src/components/listsTable/ListsTable.tsx | 10 +++++++++- .../src/components/softwareCloud/index.ts | 3 ++- src/FilterLists.Web.V2/src/hooks/useLanguages.tsx | 3 ++- src/FilterLists.Web.V2/src/hooks/useLicenses.tsx | 3 ++- src/FilterLists.Web.V2/src/hooks/useLists.tsx | 3 ++- src/FilterLists.Web.V2/src/hooks/useSoftware.tsx | 3 ++- src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx | 3 ++- src/FilterLists.Web.V2/src/hooks/useTags.tsx | 3 ++- 8 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index 538a37129..a86cdf68d 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -12,7 +12,7 @@ import { nameof } from '../../utils'; import { Description } from '../Description'; import { LanguageCloud } from '../languageCloud'; import { ListInfoButton } from '../ListInfoButton'; -import { SoftwareCloud } from '../softwareCloud'; +import { SoftwareCloud, SoftwareIcon } from '../softwareCloud'; import { TagCloud } from '../tagCloud'; import { arraySorter } from './arraySorter'; import styles from './ListsTable.module.css'; @@ -87,6 +87,14 @@ export const ListsTable = (props: RouteComponentProps & Props) => { }} width={143} className={styles.nogrow} + filters={software.map(s => ({ + text: <> +   + {s.name} + , + value: s.name + }))} + onFilter={(value, record) => software.filter((s: Software) => s.name === value).flatMap(s => s.syntaxIds).includes(record.syntaxId)} render={(syntaxId: number) => syntaxId ? s.syntaxIds.includes(syntaxId))} /> diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/index.ts b/src/FilterLists.Web.V2/src/components/softwareCloud/index.ts index 065277b3b..212ee46c3 100644 --- a/src/FilterLists.Web.V2/src/components/softwareCloud/index.ts +++ b/src/FilterLists.Web.V2/src/components/softwareCloud/index.ts @@ -1,3 +1,4 @@ import { SoftwareCloud } from './SoftwareCloud'; +import { SoftwareIcon } from './SoftwareIcon'; -export { SoftwareCloud }; \ No newline at end of file +export { SoftwareCloud, SoftwareIcon }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx b/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx index 862aee4cf..ed67cd574 100644 --- a/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx @@ -1,4 +1,5 @@ import { Language } from '../interfaces/Language'; import { useApiData } from './useApiData'; -export const useLanguages = () => useApiData("/api/v1/languages") || []; \ No newline at end of file +export const useLanguages = () => (useApiData("/api/v1/languages") || []) + .sort((a: Language, b: Language) => a.name.localeCompare(b.name)); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx b/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx index d11b6868c..0704ae603 100644 --- a/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx @@ -1,4 +1,5 @@ import { License } from '../interfaces/License'; import { useApiData } from './useApiData'; -export const useLicenses = () => useApiData("/api/v1/licenses") || []; \ No newline at end of file +export const useLicenses = () => (useApiData("/api/v1/licenses") || []) + .sort((a: License, b: License) => a.name.localeCompare(b.name)); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useLists.tsx b/src/FilterLists.Web.V2/src/hooks/useLists.tsx index b75846434..f01f960ef 100644 --- a/src/FilterLists.Web.V2/src/hooks/useLists.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useLists.tsx @@ -6,5 +6,6 @@ import { useApiData } from './useApiData'; export const useLists = () => { const lists = useApiData("/api/v1/lists"); lists && lists.forEach(l => l.slug = slugify(l.name)); - return lists || []; + return (lists || []) + .sort((a: List, b: List) => a.name.localeCompare(b.name)); }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useSoftware.tsx b/src/FilterLists.Web.V2/src/hooks/useSoftware.tsx index 18507c98f..2e21c1e0c 100644 --- a/src/FilterLists.Web.V2/src/hooks/useSoftware.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useSoftware.tsx @@ -1,4 +1,5 @@ import { Software } from '../interfaces/Software'; import { useApiData } from './useApiData'; -export const useSoftware = () => useApiData("/api/v1/software") || []; \ No newline at end of file +export const useSoftware = () => (useApiData("/api/v1/software") || []) + .sort((a: Software, b: Software) => a.name.localeCompare(b.name)); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx b/src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx index 24415f461..8a61eb92b 100644 --- a/src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx @@ -1,4 +1,5 @@ import { Syntax } from '../interfaces/Syntax'; import { useApiData } from './useApiData'; -export const useSyntaxes = () => useApiData("/api/v1/syntaxes") || []; \ No newline at end of file +export const useSyntaxes = () => (useApiData("/api/v1/syntaxes") || []) + .sort((a: Syntax, b: Syntax) => a.name.localeCompare(b.name)); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/hooks/useTags.tsx b/src/FilterLists.Web.V2/src/hooks/useTags.tsx index 1840726a4..6495c363a 100644 --- a/src/FilterLists.Web.V2/src/hooks/useTags.tsx +++ b/src/FilterLists.Web.V2/src/hooks/useTags.tsx @@ -1,4 +1,5 @@ import { Tag } from '../interfaces/Tag'; import { useApiData } from './useApiData'; -export const useTags = () => useApiData("/api/v1/tags") || []; \ No newline at end of file +export const useTags = () => (useApiData("/api/v1/tags") || []) + .sort((a: Tag, b: Tag) => a.name.localeCompare(b.name)); \ No newline at end of file From d60e5030356a54a0d2e34b68da8318ecf42d2fbf Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 13:02:44 -0500 Subject: [PATCH 159/163] add filter to Languages column --- .../src/components/listsTable/ListsTable.tsx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index a86cdf68d..ca7dd9c64 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -1,4 +1,4 @@ -import { Table } from 'antd'; +import { Table, Tag } from 'antd'; import React from 'react'; import { RouteComponentProps } from 'react-router'; @@ -7,7 +7,7 @@ import { Language } from '../../interfaces/Language'; import { License } from '../../interfaces/License'; import { List } from '../../interfaces/List'; import { Software } from '../../interfaces/Software'; -import { Tag } from '../../interfaces/Tag'; +import { Tag as TagInterface } from '../../interfaces/Tag'; import { nameof } from '../../utils'; import { Description } from '../Description'; import { LanguageCloud } from '../languageCloud'; @@ -22,7 +22,7 @@ interface Props { languages: Language[]; licenses: License[]; software: Software[]; - tags: Tag[]; + tags: TagInterface[]; }; export const ListsTable = (props: RouteComponentProps & Props) => { @@ -107,6 +107,16 @@ export const ListsTable = (props: RouteComponentProps & Props) => { sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, languages)} width={125} className={styles.nogrow} + filters={languages.map(l => ({ + text: <> + {l.iso6391}  + {l.name} + , + value: l.id.toString() + }))} + onFilter={(value, record) => record.languageIds + ? record.languageIds.includes(+value) + : false} render={(languageIds: number[]) => languageIds ? languageIds.includes(l.id))} /> @@ -121,7 +131,7 @@ export const ListsTable = (props: RouteComponentProps & Props) => { className={styles.nogrow} render={(tagIds: number[]) => tagIds - ? tagIds.includes(t.id))} /> + ? tagIds.includes(t.id))} /> : null} />} ); From ed4ef673a35b8cb53f858f8c4a84f47e52e6894e Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 13:31:10 -0500 Subject: [PATCH 160/163] add Tag column filter --- .../src/components/listsTable/ListsTable.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx index ca7dd9c64..1e84e9f51 100644 --- a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx +++ b/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx @@ -129,6 +129,13 @@ export const ListsTable = (props: RouteComponentProps & Props) => { sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, tags)} width={275} className={styles.nogrow} + filters={tags.map(t => ({ + text: {t.name}, + value: t.id.toString() + }))} + onFilter={(value, record) => record.tagIds + ? record.tagIds.includes(+value) + : false} render={(tagIds: number[]) => tagIds ? tagIds.includes(t.id))} /> From dcc29ae273852ae5417bbd0679ba0383521db79d Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 14:44:55 -0500 Subject: [PATCH 161/163] replace UI with new UI --- src/FilterLists.Web.V2/.gitignore | 21 ---- src/FilterLists.Web.V2/package-lock.json | Bin 562738 -> 0 bytes src/FilterLists.Web.V2/package.json | 43 ------- .../public/icon_filterlists.png | Bin 2163 -> 0 bytes src/FilterLists.Web.V2/public/index.html | 42 ------- .../public/logo_filterlists.png | Bin 3953 -> 0 bytes src/FilterLists.Web.V2/public/manifest.json | 15 --- src/FilterLists.Web.V2/src/App.test.tsx | 10 -- src/FilterLists.Web.V2/src/App.tsx | 90 -------------- src/FilterLists.Web.V2/src/index.css | 13 -- src/FilterLists.Web.V2/src/index.tsx | 8 -- src/FilterLists.Web.V2/src/react-app-env.d.ts | 1 - src/FilterLists.Web.V2/src/utils/index.ts | 3 - src/FilterLists.Web.V2/tsconfig.json | 26 ---- src/FilterLists.Web/.gitignore | 4 +- src/FilterLists.Web/Dockerfile | 21 ---- .../config-overrides.js | 0 src/FilterLists.Web/package-lock.json | Bin 520899 -> 562738 bytes src/FilterLists.Web/package.json | 43 ++++--- src/FilterLists.Web/public/index.html | 63 ++++++---- src/FilterLists.Web/src/App.css | 14 --- src/FilterLists.Web/src/App.test.tsx | 5 +- src/FilterLists.Web/src/App.tsx | 94 +++++++++++++-- src/FilterLists.Web/src/Layout.tsx | 60 ---------- src/FilterLists.Web/src/Router.tsx | 13 -- .../src/components/Description.tsx | 0 .../src/components/LicenseTag.tsx | 0 .../src/components/LinkButton.tsx | 0 .../src/components/ListInfoButton.tsx | 0 .../src/components/ListInfoDrawer.tsx | 0 .../src/components/PublishedDate.tsx | 0 .../src/components/SubscribeButtons.tsx | 0 .../src/components/SyntaxTag.tsx | 0 .../src/components/index.ts | 0 .../languageCloud/LanguageCloud.module.css | 0 .../languageCloud/LanguageCloud.tsx | 0 .../src/components/languageCloud/index.ts | 0 .../src/components/listsTable/ListDrawer.tsx | 0 .../listsTable/ListsTable.module.css | 0 .../src/components/listsTable/ListsTable.tsx | 0 .../components/listsTable/ListsTableHoc.tsx | 0 .../src/components/listsTable/arraySorter.ts | 0 .../src/components/listsTable/index.ts | 0 .../softwareCloud/SoftwareCloud.module.css | 0 .../softwareCloud/SoftwareCloud.tsx | 0 .../components/softwareCloud/SoftwareIcon.tsx | 0 .../softwareCloud/imgs/01-uBlock-Origin.svg | 0 .../softwareCloud/imgs/02-Adblock-Plus.svg | 0 .../softwareCloud/imgs/03-AdGuard.svg | 0 .../softwareCloud/imgs/04-DNS66.png | Bin .../softwareCloud/imgs/05-Nano-Adblocker.png | Bin .../softwareCloud/imgs/06-AdBlock.png | Bin .../softwareCloud/imgs/07-AdAway.png | Bin .../imgs/08-Personal-Blocklist.png | Bin .../softwareCloud/imgs/10-Redirector.png | Bin .../imgs/11-Hosts-File-Editor.png | Bin .../softwareCloud/imgs/12-Gas-Mask.png | Bin .../softwareCloud/imgs/13-MinerBlock.svg | 0 .../softwareCloud/imgs/14-Pi-hole.svg | 0 .../softwareCloud/imgs/15-uBlock.svg | 0 .../imgs/16-Internet-Explorer-TPL.svg | 0 .../imgs/17-Google-Hit-Hider-by-Domain.png | Bin .../softwareCloud/imgs/18-FireHOL.png | Bin .../softwareCloud/imgs/19-Samsung-Knox.png | Bin .../softwareCloud/imgs/20-Little-Snitch.png | Bin .../softwareCloud/imgs/21-Privoxy.png | Bin .../softwareCloud/imgs/22-Diversion.png | Bin .../softwareCloud/imgs/23-dnsmasq.png | Bin .../softwareCloud/imgs/24-Slimjet.png | Bin .../softwareCloud/imgs/25-uMatrix.png | Bin .../softwareCloud/imgs/26-Blokada.png | Bin .../softwareCloud/imgs/27-hostsmgr.png | Bin .../imgs/28-personalDNSfilter.svg | 0 .../softwareCloud/imgs/29-Unbound.png | Bin .../components/softwareCloud/imgs/30-BIND.png | Bin .../softwareCloud/imgs/31-AdGuard-Home.png | Bin .../softwareCloud/imgs/32-AdNauseam.png | Bin .../imgs/33-Legacy-Unix-Derivatives.png | Bin .../imgs/34-Windows-command-line.png | Bin .../components/softwareCloud/imgs/imgs.d.ts | 0 .../components/softwareCloud/imgs/index.ts | 0 .../src/components/softwareCloud/index.ts | 0 .../components/tagCloud/TagCloud.module.css | 0 .../src/components/tagCloud/TagCloud.tsx | 0 .../src/components/tagCloud/index.ts | 0 .../src/hooks/index.ts | 0 .../src/hooks/useApiData.tsx | 0 .../src/hooks/useLanguages.tsx | 0 .../src/hooks/useLicenses.tsx | 0 .../src/hooks/useLists.tsx | 0 .../src/hooks/useSearchColumnFilter.tsx | 0 .../src/hooks/useSoftware.tsx | 0 .../src/hooks/useSyntaxes.tsx | 0 .../src/hooks/useTablePageSizer.tsx | 0 .../src/hooks/useTags.tsx | 0 src/FilterLists.Web/src/index.tsx | 9 +- .../src/interfaces/Language.ts | 0 .../src/interfaces/License.ts | 0 .../src/interfaces/List.ts | 0 .../src/interfaces/Software.ts | 0 .../src/interfaces/Syntax.ts | 0 .../src/interfaces/Tag.ts | 0 src/FilterLists.Web/src/modules/home/Home.tsx | 111 ------------------ .../src/modules/home/HomeContainer.tsx | 92 --------------- .../modules/home/components/IListDetails.ts | 28 ----- .../src/modules/home/components/Oneliner.tsx | 14 --- .../src/modules/home/components/TagGroup.tsx | 67 ----------- .../detailsExpander/DetailsExpander.tsx | 28 ----- .../detailsExpander/LinkButtonGroup.tsx | 31 ----- .../home/components/detailsExpander/index.ts | 3 - .../detailsExpander/infoCard/Description.tsx | 16 --- .../detailsExpander/infoCard/InfoCard.tsx | 51 -------- .../detailsExpander/infoCard/Languages.tsx | 20 ---- .../detailsExpander/infoCard/License.tsx | 17 --- .../infoCard/PublishedDate.tsx | 13 -- .../detailsExpander/infoCard/RuleCount.tsx | 12 -- .../detailsExpander/infoCard/Syntax.tsx | 17 --- .../detailsExpander/infoCard/UpdatedDate.tsx | 15 --- .../detailsExpander/infoCard/description.css | 1 - .../detailsExpander/infoCard/index.ts | 3 - .../detailsExpander/linkButtonGroup.css | 3 - .../MaintainerInfoCard.tsx | 21 ---- .../MaintainerLinkButtonGroup.tsx | 16 --- .../MaintainersInfoCard.tsx | 14 --- .../maintainersInfoCard/index.ts | 3 - .../src/modules/home/components/index.ts | 5 - .../components/linkButtons/ChatButton.tsx | 14 --- .../components/linkButtons/DonateButton.tsx | 14 --- .../components/linkButtons/EmailButton.tsx | 14 --- .../components/linkButtons/ForumButton.tsx | 14 --- .../components/linkButtons/HomeButton.tsx | 14 --- .../components/linkButtons/IssuesButton.tsx | 14 --- .../components/linkButtons/LinkButton.tsx | 20 ---- .../components/linkButtons/PolicyButton.tsx | 14 --- .../components/linkButtons/SubmitButton.tsx | 14 --- .../SubscribeButton/SubscribeButton.tsx | 56 --------- .../SubscribeButton/SubscribeButtonGroup.tsx | 16 --- .../SubscribeButtonGroupDropdown.tsx | 30 ----- .../linkButtons/SubscribeButton/index.ts | 3 - .../components/linkButtons/TwitterButton.tsx | 14 --- .../linkButtons/ViewButton/ViewButton.tsx | 24 ---- .../ViewButton/ViewButtonGroup.tsx | 16 --- .../ViewButton/ViewButtonGroupDropdown.tsx | 30 ----- .../linkButtons/ViewButton/index.ts | 3 - .../home/components/linkButtons/index.ts | 13 -- .../home/components/listsTable/ListsTable.tsx | 96 --------------- .../listsTable/columns/DetailsButton.tsx | 30 ----- .../listsTable/columns/Languages.tsx | 72 ------------ .../components/listsTable/columns/License.tsx | 69 ----------- .../listsTable/columns/Maintainers.tsx | 69 ----------- .../components/listsTable/columns/Name.tsx | 22 ---- .../listsTable/columns/RuleCount.tsx | 28 ----- .../listsTable/columns/Software.tsx | 75 ------------ .../listsTable/columns/SubscribeButton.tsx | 24 ---- .../components/listsTable/columns/Syntax.tsx | 47 -------- .../components/listsTable/columns/Tags.tsx | 64 ---------- .../listsTable/columns/UpdatedDate.tsx | 33 ------ .../components/listsTable/columns/index.ts | 13 -- .../home/components/listsTable/index.ts | 3 - .../home/components/listsTable/listsTable.css | 16 --- .../components/softwareIcon/SoftwareIcon.tsx | 55 --------- .../softwareIcon/imgs/01-uBlock-Origin.svg | 1 - .../softwareIcon/imgs/02-Adblock-Plus.svg | 15 --- .../softwareIcon/imgs/03-AdGuard.png | Bin 893 -> 0 bytes .../softwareIcon/imgs/03-AdGuard.svg | 5 - .../components/softwareIcon/imgs/04-DNS66.png | Bin 851 -> 0 bytes .../softwareIcon/imgs/05-Nano-Adblocker.png | Bin 698 -> 0 bytes .../softwareIcon/imgs/06-AdBlock.png | Bin 1268 -> 0 bytes .../softwareIcon/imgs/07-AdAway.png | Bin 658 -> 0 bytes .../imgs/08-Personal-Blocklist.png | Bin 1295 -> 0 bytes .../softwareIcon/imgs/10-Redirector.png | Bin 547 -> 0 bytes .../imgs/11-Hosts-File-Editor.png | Bin 1113 -> 0 bytes .../softwareIcon/imgs/12-Gas-Mask.png | Bin 424 -> 0 bytes .../softwareIcon/imgs/13-MinerBlock.svg | 34 ------ .../softwareIcon/imgs/14-Pi-hole.png | Bin 700 -> 0 bytes .../softwareIcon/imgs/14-Pi-hole.svg | 1 - .../softwareIcon/imgs/15-uBlock.svg | 18 --- .../imgs/16-Internet-Explorer-TPL.png | Bin 1056 -> 0 bytes .../imgs/16-Internet-Explorer-TPL.svg | 1 - .../imgs/17-Google-Hit-Hider-by-Domain.png | Bin 636 -> 0 bytes .../softwareIcon/imgs/18-FireHOL.png | Bin 617 -> 0 bytes .../softwareIcon/imgs/19-Samsung-Knox.png | Bin 476 -> 0 bytes .../softwareIcon/imgs/20-Little-Snitch.png | Bin 1168 -> 0 bytes .../softwareIcon/imgs/21-Privoxy.png | Bin 1286 -> 0 bytes .../softwareIcon/imgs/22-Diversion.png | Bin 403 -> 0 bytes .../softwareIcon/imgs/23-dnsmasq.png | Bin 789 -> 0 bytes .../softwareIcon/imgs/24-Slimjet.png | Bin 1419 -> 0 bytes .../softwareIcon/imgs/25-uMatrix.png | Bin 917 -> 0 bytes .../softwareIcon/imgs/26-Blokada.png | Bin 998 -> 0 bytes .../softwareIcon/imgs/27-hostsmgr.png | Bin 750 -> 0 bytes .../imgs/28-personalDNSfilter.png | Bin 831 -> 0 bytes .../imgs/28-personalDNSfilter.svg | 20 ---- .../softwareIcon/imgs/29-Unbound.png | Bin 565 -> 0 bytes .../components/softwareIcon/imgs/30-BIND.png | Bin 520 -> 0 bytes .../softwareIcon/imgs/31-AdGuard-Home.png | Bin 878 -> 0 bytes .../softwareIcon/imgs/32-AdNauseam.png | Bin 713 -> 0 bytes .../imgs/33-Legacy-Unix-Derivatives.png | Bin 867 -> 0 bytes .../imgs/34-Windows-command-line.png | Bin 470 -> 0 bytes .../components/softwareIcon/imgs/imgs.d.ts | 9 -- .../components/softwareIcon/imgs/index.ts | 36 ------ .../home/components/softwareIcon/index.ts | 3 - src/FilterLists.Web/src/modules/home/index.ts | 3 - .../home/interfaces/IColumnVisibility.ts | 4 - .../src/modules/home/interfaces/ILicense.ts | 6 - .../src/modules/home/interfaces/IList.ts | 22 ---- .../modules/home/interfaces/IMaintainer.ts | 8 -- .../src/modules/home/interfaces/ISoftware.ts | 7 -- .../src/modules/home/interfaces/ISyntax.ts | 7 -- .../src/modules/home/interfaces/ITag.ts | 6 - .../src/modules/home/interfaces/Language.ts | 6 - src/FilterLists.Web/src/modules/index.ts | 3 - src/FilterLists.Web/src/react-app-env.d.ts | 2 +- src/FilterLists.Web/src/utils/GetContrast.ts | 8 -- src/FilterLists.Web/src/utils/index.ts | 4 +- src/FilterLists.Web/src/utils/loader.css | 70 ----------- .../src/utils/nameof.ts | 0 src/FilterLists.Web/tsconfig.json | 5 +- 217 files changed, 159 insertions(+), 2397 deletions(-) delete mode 100644 src/FilterLists.Web.V2/.gitignore delete mode 100644 src/FilterLists.Web.V2/package-lock.json delete mode 100644 src/FilterLists.Web.V2/package.json delete mode 100644 src/FilterLists.Web.V2/public/icon_filterlists.png delete mode 100644 src/FilterLists.Web.V2/public/index.html delete mode 100644 src/FilterLists.Web.V2/public/logo_filterlists.png delete mode 100644 src/FilterLists.Web.V2/public/manifest.json delete mode 100644 src/FilterLists.Web.V2/src/App.test.tsx delete mode 100644 src/FilterLists.Web.V2/src/App.tsx delete mode 100644 src/FilterLists.Web.V2/src/index.css delete mode 100644 src/FilterLists.Web.V2/src/index.tsx delete mode 100644 src/FilterLists.Web.V2/src/react-app-env.d.ts delete mode 100644 src/FilterLists.Web.V2/src/utils/index.ts delete mode 100644 src/FilterLists.Web.V2/tsconfig.json delete mode 100644 src/FilterLists.Web/Dockerfile rename src/{FilterLists.Web.V2 => FilterLists.Web}/config-overrides.js (100%) delete mode 100644 src/FilterLists.Web/src/App.css delete mode 100644 src/FilterLists.Web/src/Layout.tsx delete mode 100644 src/FilterLists.Web/src/Router.tsx rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/Description.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/LicenseTag.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/LinkButton.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/ListInfoButton.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/ListInfoDrawer.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/PublishedDate.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/SubscribeButtons.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/SyntaxTag.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/index.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/languageCloud/LanguageCloud.module.css (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/languageCloud/LanguageCloud.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/languageCloud/index.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/listsTable/ListDrawer.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/listsTable/ListsTable.module.css (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/listsTable/ListsTable.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/listsTable/ListsTableHoc.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/listsTable/arraySorter.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/listsTable/index.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/SoftwareCloud.module.css (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/SoftwareCloud.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/SoftwareIcon.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/01-uBlock-Origin.svg (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/02-Adblock-Plus.svg (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/03-AdGuard.svg (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/04-DNS66.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/05-Nano-Adblocker.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/06-AdBlock.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/07-AdAway.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/08-Personal-Blocklist.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/10-Redirector.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/11-Hosts-File-Editor.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/12-Gas-Mask.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/13-MinerBlock.svg (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/14-Pi-hole.svg (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/15-uBlock.svg (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/16-Internet-Explorer-TPL.svg (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/17-Google-Hit-Hider-by-Domain.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/18-FireHOL.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/19-Samsung-Knox.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/20-Little-Snitch.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/21-Privoxy.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/22-Diversion.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/23-dnsmasq.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/24-Slimjet.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/25-uMatrix.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/26-Blokada.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/27-hostsmgr.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/28-personalDNSfilter.svg (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/29-Unbound.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/30-BIND.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/31-AdGuard-Home.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/32-AdNauseam.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/33-Legacy-Unix-Derivatives.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/34-Windows-command-line.png (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/imgs.d.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/imgs/index.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/softwareCloud/index.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/tagCloud/TagCloud.module.css (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/tagCloud/TagCloud.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/components/tagCloud/index.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/index.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useApiData.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useLanguages.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useLicenses.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useLists.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useSearchColumnFilter.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useSoftware.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useSyntaxes.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useTablePageSizer.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/hooks/useTags.tsx (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/interfaces/Language.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/interfaces/License.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/interfaces/List.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/interfaces/Software.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/interfaces/Syntax.ts (100%) rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/interfaces/Tag.ts (100%) delete mode 100644 src/FilterLists.Web/src/modules/home/Home.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/HomeContainer.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/IListDetails.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/Oneliner.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/TagGroup.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/DetailsExpander.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/LinkButtonGroup.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Description.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/InfoCard.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Languages.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/License.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/PublishedDate.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/RuleCount.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Syntax.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/UpdatedDate.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/description.css delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/linkButtonGroup.css delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainerInfoCard.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainerLinkButtonGroup.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainersInfoCard.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/ChatButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/DonateButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/EmailButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/ForumButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/HomeButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/IssuesButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/LinkButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/PolicyButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/SubmitButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButtonGroup.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButtonGroupDropdown.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/TwitterButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButtonGroup.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButtonGroupDropdown.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/linkButtons/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/ListsTable.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/DetailsButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/Languages.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/License.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/Maintainers.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/Name.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/RuleCount.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/Software.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/SubscribeButton.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/Syntax.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/Tags.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/UpdatedDate.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/columns/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/listsTable/listsTable.css delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/SoftwareIcon.tsx delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/01-uBlock-Origin.svg delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/02-Adblock-Plus.svg delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/03-AdGuard.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/03-AdGuard.svg delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/04-DNS66.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/05-Nano-Adblocker.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/06-AdBlock.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/07-AdAway.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/08-Personal-Blocklist.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/10-Redirector.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/11-Hosts-File-Editor.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/12-Gas-Mask.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/13-MinerBlock.svg delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/14-Pi-hole.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/14-Pi-hole.svg delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/15-uBlock.svg delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/16-Internet-Explorer-TPL.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/16-Internet-Explorer-TPL.svg delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/17-Google-Hit-Hider-by-Domain.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/18-FireHOL.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/19-Samsung-Knox.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/20-Little-Snitch.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/21-Privoxy.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/22-Diversion.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/23-dnsmasq.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/24-Slimjet.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/25-uMatrix.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/26-Blokada.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/27-hostsmgr.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/28-personalDNSfilter.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/28-personalDNSfilter.svg delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/29-Unbound.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/30-BIND.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/31-AdGuard-Home.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/32-AdNauseam.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/33-Legacy-Unix-Derivatives.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/34-Windows-command-line.png delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/imgs.d.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/components/softwareIcon/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/index.ts delete mode 100644 src/FilterLists.Web/src/modules/home/interfaces/IColumnVisibility.ts delete mode 100644 src/FilterLists.Web/src/modules/home/interfaces/ILicense.ts delete mode 100644 src/FilterLists.Web/src/modules/home/interfaces/IList.ts delete mode 100644 src/FilterLists.Web/src/modules/home/interfaces/IMaintainer.ts delete mode 100644 src/FilterLists.Web/src/modules/home/interfaces/ISoftware.ts delete mode 100644 src/FilterLists.Web/src/modules/home/interfaces/ISyntax.ts delete mode 100644 src/FilterLists.Web/src/modules/home/interfaces/ITag.ts delete mode 100644 src/FilterLists.Web/src/modules/home/interfaces/Language.ts delete mode 100644 src/FilterLists.Web/src/modules/index.ts delete mode 100644 src/FilterLists.Web/src/utils/GetContrast.ts delete mode 100644 src/FilterLists.Web/src/utils/loader.css rename src/{FilterLists.Web.V2 => FilterLists.Web}/src/utils/nameof.ts (100%) diff --git a/src/FilterLists.Web.V2/.gitignore b/src/FilterLists.Web.V2/.gitignore deleted file mode 100644 index 9f6f0d08b..000000000 --- a/src/FilterLists.Web.V2/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* \ No newline at end of file diff --git a/src/FilterLists.Web.V2/package-lock.json b/src/FilterLists.Web.V2/package-lock.json deleted file mode 100644 index 824648eadb1865f52a209e5648b7af6fb3e8e2df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 562738 zcmeFa*^=r?vMBi8Us1Lno6fCSz%{#O1(Fa*AdncvL$zrh&^&;oYvke>;I{L+#5;i zghBl~{5SG9eEQZ4wH+94tlob`j-wMJ&Yi?a!SF1}jpKK^5gCDQ1e$aF{{Mhk!My)g zg6vHJPWX2o#ua>=OA$Xr6 zdxB9IU=+Vy#p@V-0IbIEgRkF?(7wlZCq1;F1DUiGM%7zWjzmK@oHKYuXAoAJVyXM; zdQb(SnYl@44~5Y*J+SVi1x=Q4GFK!<^>ToAe@hm+p$((CGDi>JW82D)tOU>upP9Qx zEkN!;NdhOZjx@l*kJ$G#Z~)$)u`yucUu5Is>;TKhf8UPteUDa`8n$-m%JqT}m)9O? z5f~8+CAd2~P>jFm^F5Ya#e-I2?~?gU8k<(MM14iE4(fI`c9mhiBsd+R2O`RIk(iIj zobA+TeaeWZYs)O>MSq;fj(14cXop7=YO$VA7Op?ov?pd{w)W6LcLoNuq2h(zfZIN+ zr6Ye~@0#_@e5#@v-dmCfnRC+3{~`ZINx-0w^}umBP;a{NW+o?Xeo-j53cUR{@i+0h z;D4O`s7WuN-j0)gk8!lEd(DX&;6CYg{I^ zP5c8`OpGJ`5~C^R96S!^3Cb@r&46itm*--Ch4*sNVrNTjwwWZ|F)=CSUbchD3MM
ZG=w4EF&-yB@2@; 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�R0)mPgmI#!^^JU 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ΠF;>%+&U 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 ylX*08M@7F^5UIgK#<_)Mr0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/public/icon_filterlists.png b/src/FilterLists.Web.V2/public/icon_filterlists.png deleted file mode 100644 index 99c15bdde8dc8d089b942715967f19ba58848f0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2163 zcmc&#YgAKL7C!eHB*8+lI!ihNrBaG*ja(lPOcWD&M5-ZBd88l`h9WjJi4jN&7;-I6 z?F`t|KGYg{_@YW0o+}WNNyx%coKcu+jMzK~9ohg13D`=ogvZ==e$9{m(ABl({Mp~$ zd+l#O&OYn>B{hZa@ApSP0Dyn;?u54hfH4RIJPs2F1i=DK;EHGr8UXFm74!K%m>yQJ z`z;0l6|Vw-9tU6!Goj-Elpz2(*Z`2v0|zkM7}?=>mQhxlUA%K7$+e^ZghPKQ%UIsR=L zDp17D;p@|xA^4!5Rx{2R7}`&djS;y2;e~A(|{+opP%rT|9Fs{6iuKKF}7@+J{g~)C+=k53DMuAu~XMV zSLF`%6;n5#pEMcc-94e%f(y z2u_u>gw8ZxV~}7yfLPreTRGpSaWS>d(}qKj!KqW~Ky)s*%#yrM7SjSD`e-ym?#Wf- zSuh42v9(Fbn3=$*9+5Km@5!sos&CtQ<|7Msg@8* z0nE9=yxBr|lQ5j`bE0EwH{T!{(7LXGT8Ao9Y~*`S)}Zk&Fr0@w`mj*qWPzL7<+t6jHzD;L>VLu@l1GXbtKz1_-4@k!IQRcH$46F{CCq- z{C%I{1Gam$!KKqb?Cj=nBc9_}o69G0c>TS9V&u(<;AYos#cp~YNKzIXGRCmvgBs2j zkNHCX@FGt$Sr%1!H(dzF*UcMsXSD7P1vU@$kak?gX@5ER&?DOcug$}Vs<0|S?OL=` z=Tear=S<2~=*uud!bX_q?b-qb4P_K9T;WRi*87>@LxTREPKM2WQ2hcb5P{Znn#n|G zlaTAf{s?RsaA_uTi?kiff`%AVrm|syToVGqRaWRdwc}z9?`F$)w@zm&vXv@)?EUi+ z$;!j#CWh?P)Uv%zeJ2RtC5^B;tCskZXIn#{rz1c6#X%)|i%fHepzA@B$F4K1$ zvRd|+AuHbFslBdV_eGM{;pG@k#zz7R6U0r`RNXaHJrKz48voh+Nzi2XxYQFJLtjb^)Pz&WH-*2YU(HiHss^@MLT&#hJmUOf?T2`|7XFnYs^{>jA&gnkIYTyA~yB z-P|>~%Jvm)%bs!Pez&kEQS+;AY&+eTPhhRUNFz!US*7pfmll!>juc`7Y(_S1BO - - - - - - - - - FilterLists | Subscriptions for uBlock Origin, Adblock Plus, AdGuard, ... - - - - - - - - - - - diff --git a/src/FilterLists.Web.V2/public/logo_filterlists.png b/src/FilterLists.Web.V2/public/logo_filterlists.png deleted file mode 100644 index 7d8d1817038c2ed8604825a8b526e2def1bb3e7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3953 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 diff --git a/src/FilterLists.Web.V2/public/manifest.json b/src/FilterLists.Web.V2/public/manifest.json deleted file mode 100644 index 143de534b..000000000 --- a/src/FilterLists.Web.V2/public/manifest.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "short_name": "FilterLists", - "name": "FilterLists | Subscriptions for uBlock Origin, Adblock Plus, AdGuard, ...", - "icons": [ - { - "src": "icon_filterlists.png", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/png" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/App.test.tsx b/src/FilterLists.Web.V2/src/App.test.tsx deleted file mode 100644 index 7911e5b41..000000000 --- a/src/FilterLists.Web.V2/src/App.test.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; - -import { App } from './App'; - -it('renders without crashing', () => { - const div = document.createElement('div'); - ReactDOM.render(, div); - ReactDOM.unmountComponentAtNode(div); -}); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/App.tsx b/src/FilterLists.Web.V2/src/App.tsx deleted file mode 100644 index e2ac34738..000000000 --- a/src/FilterLists.Web.V2/src/App.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { Icon, Layout, Menu } from 'antd'; -import React from 'react'; -import { BrowserRouter as Router, Route, RouteComponentProps, Switch } from 'react-router-dom'; - -import { ListsTable } from './components'; - -const { Header, Content, Footer } = Layout; - -export const App: React.FC = () => - - -
- - -
- -
- - - - -
-
-
- | | | | | -
-
-
; - -const Logo = () => - FilterLists logo; - -const NotFound = (props: RouteComponentProps) => -

- 404 Not Found: {props.location.pathname} -

; - -const CopyrightAuthor = () => - <> - ©{new Date().getFullYear()}  - - Collin M. Barrett - - ; - -const Twitter = () => - - Twitter - ; - -const Community = () => - - Community - ; - -const GitHub = () => - - GitHub - ; - -const Api = () => - - API - ; - -const Donate = () => - - Donate - ; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/index.css b/src/FilterLists.Web.V2/src/index.css deleted file mode 100644 index 4a1df4db7..000000000 --- a/src/FilterLists.Web.V2/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; -} diff --git a/src/FilterLists.Web.V2/src/index.tsx b/src/FilterLists.Web.V2/src/index.tsx deleted file mode 100644 index 8fec59ed5..000000000 --- a/src/FilterLists.Web.V2/src/index.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import './index.css'; - -import React from 'react'; -import ReactDOM from 'react-dom'; - -import { App } from './App'; - -ReactDOM.render(, document.getElementById('root')); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/react-app-env.d.ts b/src/FilterLists.Web.V2/src/react-app-env.d.ts deleted file mode 100644 index 6889c6b37..000000000 --- a/src/FilterLists.Web.V2/src/react-app-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/utils/index.ts b/src/FilterLists.Web.V2/src/utils/index.ts deleted file mode 100644 index d22b49973..000000000 --- a/src/FilterLists.Web.V2/src/utils/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { nameof } from './nameof'; - -export { nameof }; \ No newline at end of file diff --git a/src/FilterLists.Web.V2/tsconfig.json b/src/FilterLists.Web.V2/tsconfig.json deleted file mode 100644 index 213390d38..000000000 --- a/src/FilterLists.Web.V2/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "noImplicitAny": true - }, - "include": [ - "src" - ] -} \ No newline at end of file diff --git a/src/FilterLists.Web/.gitignore b/src/FilterLists.Web/.gitignore index 4d29575de..9f6f0d08b 100644 --- a/src/FilterLists.Web/.gitignore +++ b/src/FilterLists.Web/.gitignore @@ -1,5 +1,3 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - # dependencies /node_modules /.pnp @@ -20,4 +18,4 @@ npm-debug.log* yarn-debug.log* -yarn-error.log* +yarn-error.log* \ No newline at end of file diff --git a/src/FilterLists.Web/Dockerfile b/src/FilterLists.Web/Dockerfile deleted file mode 100644 index a6dd8bcb4..000000000 --- a/src/FilterLists.Web/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -# Context: . -# Command: docker build -f src/FilterLists.Web/Dockerfile . - -# init base -FROM nginx:alpine as base - -# init build -FROM node:alpine as build - -# install -WORKDIR /usr/src/app/ -COPY src/FilterLists.Web/package*.json ./ -RUN npm install --only=prod - -# build -COPY src/FilterLists.Web/. ./ -RUN INLINE_RUNTIME_CHUNK=false npm run build - -# final -FROM base as final -COPY --from=build /usr/src/app/build /usr/share/nginx/html \ No newline at end of file diff --git a/src/FilterLists.Web.V2/config-overrides.js b/src/FilterLists.Web/config-overrides.js similarity index 100% rename from src/FilterLists.Web.V2/config-overrides.js rename to src/FilterLists.Web/config-overrides.js diff --git a/src/FilterLists.Web/package-lock.json b/src/FilterLists.Web/package-lock.json index c550b33d1cce95e8ea39a83d8746538fad329f52..824648eadb1865f52a209e5648b7af6fb3e8e2df 100644 GIT binary patch delta 53576 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 BLSO&@ delta 33307 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 + + + + + + + + FilterLists | Subscriptions for uBlock Origin, Adblock Plus, AdGuard, ... + + + + + - - - - - - - FilterLists | Subscriptions for uBlock Origin, Adblock Plus, AdGuard, ... - - - - - - - -
-

FilterLists is built with ReactJS and therefore requires first-party JavaScript to be enabled. We do not use any - third-party JavaScript, and your privacy is very important to us. If you prefer not to enable JavaScript or your - browser does not support it, the data is also available on our GitHub repo.

-
- - - \ No newline at end of file + + +
+

+ FilterLists is built with ReactJS and therefore requires first-party + JavaScript to be enabled. We do not use any third-party JavaScript, and + your privacy is very important to us. If you prefer not to enable + JavaScript or your browser does not support it, the data is also + available on + our GitHub repo. +

+
+ + diff --git a/src/FilterLists.Web/src/App.css b/src/FilterLists.Web/src/App.css deleted file mode 100644 index 021a9f2fc..000000000 --- a/src/FilterLists.Web/src/App.css +++ /dev/null @@ -1,14 +0,0 @@ -/* use consistent and smaller font size globally */ -body, -h2, -h3, -h4, -h5, -blockquote { - font-size: 16px; -} - -/* leave a bit of horizontal padding around the app for cleanliness */ -.container { - max-width: 90vw; -} diff --git a/src/FilterLists.Web/src/App.test.tsx b/src/FilterLists.Web/src/App.test.tsx index a754b201b..7911e5b41 100644 --- a/src/FilterLists.Web/src/App.test.tsx +++ b/src/FilterLists.Web/src/App.test.tsx @@ -1,9 +1,10 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import App from './App'; + +import { App } from './App'; it('renders without crashing', () => { const div = document.createElement('div'); ReactDOM.render(, div); ReactDOM.unmountComponentAtNode(div); -}); +}); \ No newline at end of file diff --git a/src/FilterLists.Web/src/App.tsx b/src/FilterLists.Web/src/App.tsx index 8ef9be137..e2ac34738 100644 --- a/src/FilterLists.Web/src/App.tsx +++ b/src/FilterLists.Web/src/App.tsx @@ -1,14 +1,90 @@ +import { Icon, Layout, Menu } from 'antd'; import React from 'react'; -import './App.css'; -import { Layout } from "./Layout"; -import { Router } from "./Router"; +import { BrowserRouter as Router, Route, RouteComponentProps, Switch } from 'react-router-dom'; -const App: React.FC = () => { - return ( +import { ListsTable } from './components'; + +const { Header, Content, Footer } = Layout; + +export const App: React.FC = () => + - +
+ + +
+ +
+ + + + +
+
+
+ | | | | | +
- ); -} +
; -export default App; +const Logo = () => + FilterLists logo; + +const NotFound = (props: RouteComponentProps) => +

+ 404 Not Found: {props.location.pathname} +

; + +const CopyrightAuthor = () => + <> + ©{new Date().getFullYear()}  + + Collin M. Barrett + + ; + +const Twitter = () => + + Twitter + ; + +const Community = () => + + Community + ; + +const GitHub = () => + + GitHub + ; + +const Api = () => + + API + ; + +const Donate = () => + + Donate + ; \ No newline at end of file diff --git a/src/FilterLists.Web/src/Layout.tsx b/src/FilterLists.Web/src/Layout.tsx deleted file mode 100644 index e98fe8ded..000000000 --- a/src/FilterLists.Web/src/Layout.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import * as React from "react"; - -interface Props { - children?: React.ReactNode; -}; - -export const Layout = (props: Props) => -
-
-
-
- {props.children} -
-
-
-
; - -const Header = () => -
-

- - FilterLists - -

-
; - -const Footer = () => -
-

- | | | | By -

-
; - -const HubLink = () => - - Hub - ; - -const GitHubLink = () => - - GitHub - ; - -const ApiLink = () => - - API - ; - -const DonateLink = () => - - Donate - ; - -const OwnerLink = () => - - Collin M. Barrett - ; \ No newline at end of file diff --git a/src/FilterLists.Web/src/Router.tsx b/src/FilterLists.Web/src/Router.tsx deleted file mode 100644 index 6036178a7..000000000 --- a/src/FilterLists.Web/src/Router.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from "react"; -import { BrowserRouter, Redirect, Route, Switch } from "react-router-dom"; -import { Home } from "./modules"; - -const Routes = - - - - - - ; - -export const Router = () => \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/components/Description.tsx b/src/FilterLists.Web/src/components/Description.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/Description.tsx rename to src/FilterLists.Web/src/components/Description.tsx diff --git a/src/FilterLists.Web.V2/src/components/LicenseTag.tsx b/src/FilterLists.Web/src/components/LicenseTag.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/LicenseTag.tsx rename to src/FilterLists.Web/src/components/LicenseTag.tsx diff --git a/src/FilterLists.Web.V2/src/components/LinkButton.tsx b/src/FilterLists.Web/src/components/LinkButton.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/LinkButton.tsx rename to src/FilterLists.Web/src/components/LinkButton.tsx diff --git a/src/FilterLists.Web.V2/src/components/ListInfoButton.tsx b/src/FilterLists.Web/src/components/ListInfoButton.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/ListInfoButton.tsx rename to src/FilterLists.Web/src/components/ListInfoButton.tsx diff --git a/src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx b/src/FilterLists.Web/src/components/ListInfoDrawer.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/ListInfoDrawer.tsx rename to src/FilterLists.Web/src/components/ListInfoDrawer.tsx diff --git a/src/FilterLists.Web.V2/src/components/PublishedDate.tsx b/src/FilterLists.Web/src/components/PublishedDate.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/PublishedDate.tsx rename to src/FilterLists.Web/src/components/PublishedDate.tsx diff --git a/src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx b/src/FilterLists.Web/src/components/SubscribeButtons.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/SubscribeButtons.tsx rename to src/FilterLists.Web/src/components/SubscribeButtons.tsx diff --git a/src/FilterLists.Web.V2/src/components/SyntaxTag.tsx b/src/FilterLists.Web/src/components/SyntaxTag.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/SyntaxTag.tsx rename to src/FilterLists.Web/src/components/SyntaxTag.tsx diff --git a/src/FilterLists.Web.V2/src/components/index.ts b/src/FilterLists.Web/src/components/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/index.ts rename to src/FilterLists.Web/src/components/index.ts diff --git a/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.module.css b/src/FilterLists.Web/src/components/languageCloud/LanguageCloud.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.module.css rename to src/FilterLists.Web/src/components/languageCloud/LanguageCloud.module.css diff --git a/src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx b/src/FilterLists.Web/src/components/languageCloud/LanguageCloud.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/languageCloud/LanguageCloud.tsx rename to src/FilterLists.Web/src/components/languageCloud/LanguageCloud.tsx diff --git a/src/FilterLists.Web.V2/src/components/languageCloud/index.ts b/src/FilterLists.Web/src/components/languageCloud/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/languageCloud/index.ts rename to src/FilterLists.Web/src/components/languageCloud/index.ts diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx b/src/FilterLists.Web/src/components/listsTable/ListDrawer.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/listsTable/ListDrawer.tsx rename to src/FilterLists.Web/src/components/listsTable/ListDrawer.tsx diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.module.css b/src/FilterLists.Web/src/components/listsTable/ListsTable.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/components/listsTable/ListsTable.module.css rename to src/FilterLists.Web/src/components/listsTable/ListsTable.module.css diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx b/src/FilterLists.Web/src/components/listsTable/ListsTable.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/listsTable/ListsTable.tsx rename to src/FilterLists.Web/src/components/listsTable/ListsTable.tsx diff --git a/src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx b/src/FilterLists.Web/src/components/listsTable/ListsTableHoc.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/listsTable/ListsTableHoc.tsx rename to src/FilterLists.Web/src/components/listsTable/ListsTableHoc.tsx diff --git a/src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts b/src/FilterLists.Web/src/components/listsTable/arraySorter.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/listsTable/arraySorter.ts rename to src/FilterLists.Web/src/components/listsTable/arraySorter.ts diff --git a/src/FilterLists.Web.V2/src/components/listsTable/index.ts b/src/FilterLists.Web/src/components/listsTable/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/listsTable/index.ts rename to src/FilterLists.Web/src/components/listsTable/index.ts diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareCloud.module.css b/src/FilterLists.Web/src/components/softwareCloud/SoftwareCloud.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareCloud.module.css rename to src/FilterLists.Web/src/components/softwareCloud/SoftwareCloud.module.css diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareCloud.tsx b/src/FilterLists.Web/src/components/softwareCloud/SoftwareCloud.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareCloud.tsx rename to src/FilterLists.Web/src/components/softwareCloud/SoftwareCloud.tsx diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareIcon.tsx b/src/FilterLists.Web/src/components/softwareCloud/SoftwareIcon.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/SoftwareIcon.tsx rename to src/FilterLists.Web/src/components/softwareCloud/SoftwareIcon.tsx diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/01-uBlock-Origin.svg b/src/FilterLists.Web/src/components/softwareCloud/imgs/01-uBlock-Origin.svg similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/01-uBlock-Origin.svg rename to src/FilterLists.Web/src/components/softwareCloud/imgs/01-uBlock-Origin.svg diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/02-Adblock-Plus.svg b/src/FilterLists.Web/src/components/softwareCloud/imgs/02-Adblock-Plus.svg similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/02-Adblock-Plus.svg rename to src/FilterLists.Web/src/components/softwareCloud/imgs/02-Adblock-Plus.svg diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/03-AdGuard.svg b/src/FilterLists.Web/src/components/softwareCloud/imgs/03-AdGuard.svg similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/03-AdGuard.svg rename to src/FilterLists.Web/src/components/softwareCloud/imgs/03-AdGuard.svg diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/04-DNS66.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/04-DNS66.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/04-DNS66.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/04-DNS66.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/05-Nano-Adblocker.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/05-Nano-Adblocker.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/05-Nano-Adblocker.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/05-Nano-Adblocker.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/06-AdBlock.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/06-AdBlock.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/06-AdBlock.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/06-AdBlock.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/07-AdAway.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/07-AdAway.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/07-AdAway.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/07-AdAway.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/08-Personal-Blocklist.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/08-Personal-Blocklist.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/08-Personal-Blocklist.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/08-Personal-Blocklist.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/10-Redirector.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/10-Redirector.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/10-Redirector.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/10-Redirector.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/11-Hosts-File-Editor.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/11-Hosts-File-Editor.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/11-Hosts-File-Editor.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/11-Hosts-File-Editor.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/12-Gas-Mask.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/12-Gas-Mask.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/12-Gas-Mask.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/12-Gas-Mask.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/13-MinerBlock.svg b/src/FilterLists.Web/src/components/softwareCloud/imgs/13-MinerBlock.svg similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/13-MinerBlock.svg rename to src/FilterLists.Web/src/components/softwareCloud/imgs/13-MinerBlock.svg diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/14-Pi-hole.svg b/src/FilterLists.Web/src/components/softwareCloud/imgs/14-Pi-hole.svg similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/14-Pi-hole.svg rename to src/FilterLists.Web/src/components/softwareCloud/imgs/14-Pi-hole.svg diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/15-uBlock.svg b/src/FilterLists.Web/src/components/softwareCloud/imgs/15-uBlock.svg similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/15-uBlock.svg rename to src/FilterLists.Web/src/components/softwareCloud/imgs/15-uBlock.svg diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/16-Internet-Explorer-TPL.svg b/src/FilterLists.Web/src/components/softwareCloud/imgs/16-Internet-Explorer-TPL.svg similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/16-Internet-Explorer-TPL.svg rename to src/FilterLists.Web/src/components/softwareCloud/imgs/16-Internet-Explorer-TPL.svg diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/17-Google-Hit-Hider-by-Domain.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/17-Google-Hit-Hider-by-Domain.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/17-Google-Hit-Hider-by-Domain.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/17-Google-Hit-Hider-by-Domain.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/18-FireHOL.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/18-FireHOL.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/18-FireHOL.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/18-FireHOL.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/19-Samsung-Knox.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/19-Samsung-Knox.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/19-Samsung-Knox.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/19-Samsung-Knox.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/20-Little-Snitch.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/20-Little-Snitch.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/20-Little-Snitch.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/20-Little-Snitch.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/21-Privoxy.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/21-Privoxy.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/21-Privoxy.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/21-Privoxy.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/22-Diversion.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/22-Diversion.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/22-Diversion.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/22-Diversion.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/23-dnsmasq.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/23-dnsmasq.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/23-dnsmasq.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/23-dnsmasq.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/24-Slimjet.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/24-Slimjet.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/24-Slimjet.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/24-Slimjet.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/25-uMatrix.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/25-uMatrix.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/25-uMatrix.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/25-uMatrix.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/26-Blokada.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/26-Blokada.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/26-Blokada.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/26-Blokada.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/27-hostsmgr.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/27-hostsmgr.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/27-hostsmgr.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/27-hostsmgr.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/28-personalDNSfilter.svg b/src/FilterLists.Web/src/components/softwareCloud/imgs/28-personalDNSfilter.svg similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/28-personalDNSfilter.svg rename to src/FilterLists.Web/src/components/softwareCloud/imgs/28-personalDNSfilter.svg diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/29-Unbound.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/29-Unbound.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/29-Unbound.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/29-Unbound.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/30-BIND.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/30-BIND.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/30-BIND.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/30-BIND.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/31-AdGuard-Home.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/31-AdGuard-Home.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/31-AdGuard-Home.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/31-AdGuard-Home.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/32-AdNauseam.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/32-AdNauseam.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/32-AdNauseam.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/32-AdNauseam.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/33-Legacy-Unix-Derivatives.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/33-Legacy-Unix-Derivatives.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/33-Legacy-Unix-Derivatives.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/33-Legacy-Unix-Derivatives.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/34-Windows-command-line.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/34-Windows-command-line.png similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/34-Windows-command-line.png rename to src/FilterLists.Web/src/components/softwareCloud/imgs/34-Windows-command-line.png diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/imgs.d.ts b/src/FilterLists.Web/src/components/softwareCloud/imgs/imgs.d.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/imgs.d.ts rename to src/FilterLists.Web/src/components/softwareCloud/imgs/imgs.d.ts diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/imgs/index.ts b/src/FilterLists.Web/src/components/softwareCloud/imgs/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/imgs/index.ts rename to src/FilterLists.Web/src/components/softwareCloud/imgs/index.ts diff --git a/src/FilterLists.Web.V2/src/components/softwareCloud/index.ts b/src/FilterLists.Web/src/components/softwareCloud/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/softwareCloud/index.ts rename to src/FilterLists.Web/src/components/softwareCloud/index.ts diff --git a/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.module.css b/src/FilterLists.Web/src/components/tagCloud/TagCloud.module.css similarity index 100% rename from src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.module.css rename to src/FilterLists.Web/src/components/tagCloud/TagCloud.module.css diff --git a/src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx b/src/FilterLists.Web/src/components/tagCloud/TagCloud.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/components/tagCloud/TagCloud.tsx rename to src/FilterLists.Web/src/components/tagCloud/TagCloud.tsx diff --git a/src/FilterLists.Web.V2/src/components/tagCloud/index.ts b/src/FilterLists.Web/src/components/tagCloud/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/components/tagCloud/index.ts rename to src/FilterLists.Web/src/components/tagCloud/index.ts diff --git a/src/FilterLists.Web.V2/src/hooks/index.ts b/src/FilterLists.Web/src/hooks/index.ts similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/index.ts rename to src/FilterLists.Web/src/hooks/index.ts diff --git a/src/FilterLists.Web.V2/src/hooks/useApiData.tsx b/src/FilterLists.Web/src/hooks/useApiData.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useApiData.tsx rename to src/FilterLists.Web/src/hooks/useApiData.tsx diff --git a/src/FilterLists.Web.V2/src/hooks/useLanguages.tsx b/src/FilterLists.Web/src/hooks/useLanguages.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useLanguages.tsx rename to src/FilterLists.Web/src/hooks/useLanguages.tsx diff --git a/src/FilterLists.Web.V2/src/hooks/useLicenses.tsx b/src/FilterLists.Web/src/hooks/useLicenses.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useLicenses.tsx rename to src/FilterLists.Web/src/hooks/useLicenses.tsx diff --git a/src/FilterLists.Web.V2/src/hooks/useLists.tsx b/src/FilterLists.Web/src/hooks/useLists.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useLists.tsx rename to src/FilterLists.Web/src/hooks/useLists.tsx diff --git a/src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx b/src/FilterLists.Web/src/hooks/useSearchColumnFilter.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx rename to src/FilterLists.Web/src/hooks/useSearchColumnFilter.tsx diff --git a/src/FilterLists.Web.V2/src/hooks/useSoftware.tsx b/src/FilterLists.Web/src/hooks/useSoftware.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useSoftware.tsx rename to src/FilterLists.Web/src/hooks/useSoftware.tsx diff --git a/src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx b/src/FilterLists.Web/src/hooks/useSyntaxes.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useSyntaxes.tsx rename to src/FilterLists.Web/src/hooks/useSyntaxes.tsx diff --git a/src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx b/src/FilterLists.Web/src/hooks/useTablePageSizer.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useTablePageSizer.tsx rename to src/FilterLists.Web/src/hooks/useTablePageSizer.tsx diff --git a/src/FilterLists.Web.V2/src/hooks/useTags.tsx b/src/FilterLists.Web/src/hooks/useTags.tsx similarity index 100% rename from src/FilterLists.Web.V2/src/hooks/useTags.tsx rename to src/FilterLists.Web/src/hooks/useTags.tsx diff --git a/src/FilterLists.Web/src/index.tsx b/src/FilterLists.Web/src/index.tsx index 90ba2def7..8fec59ed5 100644 --- a/src/FilterLists.Web/src/index.tsx +++ b/src/FilterLists.Web/src/index.tsx @@ -1,7 +1,8 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import '../node_modules/bootstrap/dist/css/bootstrap.min.css'; -import App from './App'; import './index.css'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { App } from './App'; + ReactDOM.render(, document.getElementById('root')); \ No newline at end of file diff --git a/src/FilterLists.Web.V2/src/interfaces/Language.ts b/src/FilterLists.Web/src/interfaces/Language.ts similarity index 100% rename from src/FilterLists.Web.V2/src/interfaces/Language.ts rename to src/FilterLists.Web/src/interfaces/Language.ts diff --git a/src/FilterLists.Web.V2/src/interfaces/License.ts b/src/FilterLists.Web/src/interfaces/License.ts similarity index 100% rename from src/FilterLists.Web.V2/src/interfaces/License.ts rename to src/FilterLists.Web/src/interfaces/License.ts diff --git a/src/FilterLists.Web.V2/src/interfaces/List.ts b/src/FilterLists.Web/src/interfaces/List.ts similarity index 100% rename from src/FilterLists.Web.V2/src/interfaces/List.ts rename to src/FilterLists.Web/src/interfaces/List.ts diff --git a/src/FilterLists.Web.V2/src/interfaces/Software.ts b/src/FilterLists.Web/src/interfaces/Software.ts similarity index 100% rename from src/FilterLists.Web.V2/src/interfaces/Software.ts rename to src/FilterLists.Web/src/interfaces/Software.ts diff --git a/src/FilterLists.Web.V2/src/interfaces/Syntax.ts b/src/FilterLists.Web/src/interfaces/Syntax.ts similarity index 100% rename from src/FilterLists.Web.V2/src/interfaces/Syntax.ts rename to src/FilterLists.Web/src/interfaces/Syntax.ts diff --git a/src/FilterLists.Web.V2/src/interfaces/Tag.ts b/src/FilterLists.Web/src/interfaces/Tag.ts similarity index 100% rename from src/FilterLists.Web.V2/src/interfaces/Tag.ts rename to src/FilterLists.Web/src/interfaces/Tag.ts diff --git a/src/FilterLists.Web/src/modules/home/Home.tsx b/src/FilterLists.Web/src/modules/home/Home.tsx deleted file mode 100644 index 34350686b..000000000 --- a/src/FilterLists.Web/src/modules/home/Home.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import * as React from "react"; -import { ListsTable, Oneliner } from "./components"; -import { IColumnVisibility } from "./interfaces/IColumnVisibility"; -import { ILicense } from "./interfaces/ILicense"; -import { IList } from "./interfaces/IList"; -import { IMaintainer } from "./interfaces/IMaintainer"; -import { ISoftware } from "./interfaces/ISoftware"; -import { ISyntax } from "./interfaces/ISyntax"; -import { ITag } from "./interfaces/ITag"; -import { Language } from "./interfaces/Language"; - -const columnVisibilityDefaults: IColumnVisibility[] = [ - { column: "Software", visible: true }, - { column: "Languages", visible: true }, - { column: "Tags", visible: true }, - { column: "License", visible: false }, - { column: "Maintainers", visible: false }, - { column: "Subscribe", visible: false } -]; - -interface Props { - languages: Language[]; - licenses: ILicense[]; - lists: IList[]; - maintainers: IMaintainer[]; - software: ISoftware[]; - syntaxes: ISyntax[]; - tags: ITag[]; -}; - -interface IState { - columnVisibility: IColumnVisibility[]; - pageSize: number; -}; - -export class Home extends React.Component { - constructor(props: Props) { - super(props); - this.state = { - columnVisibility: columnVisibilityDefaults, - pageSize: 20 - }; - this.updatePageSize = this.updatePageSize.bind(this); - } - - componentDidMount() { - this.setMobileColumnVisibility(); - this.updatePageSize(); - }; - - setMobileColumnVisibility() { - if (window.innerWidth < 768) { - this.state.columnVisibility.forEach((c: IColumnVisibility) => { - c.visible = false; - }); - } - }; - - updatePageSize() { - this.setState({ - pageSize: Math.max(Math.floor((window.innerHeight - 340) / 55), 5) - }); - }; - - render() { - return
- - - {this.renderColumnVisibilityCheckboxes()} -
; - }; - - renderColumnVisibilityCheckboxes() { - return this.props.lists.length > 0 - ?
- Visible:  {this.state.columnVisibility.map( - (c: IColumnVisibility, i: number) => this.renderColumnVisibilityCheckbox(c, i))} -
- : null; - }; - - renderColumnVisibilityCheckbox(props: IColumnVisibility, key: number) { - return
- this.checkColumn(props)} /> - -
; - }; - - checkColumn(props: IColumnVisibility) { - const columnVisibility = this.state.columnVisibility; - const index = this.findWithAttr(columnVisibility, "column", props.column); - columnVisibility[index].visible = !columnVisibility[index].visible; - this.forceUpdate(); - }; - - findWithAttr(array: any, attr: string, value: string) { - for (let i = 0; i < array.length; i += 1) { - if (array[i][attr] === value) { - return i; - } - } - return -1; - }; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/HomeContainer.tsx b/src/FilterLists.Web/src/modules/home/HomeContainer.tsx deleted file mode 100644 index 0c0ea906a..000000000 --- a/src/FilterLists.Web/src/modules/home/HomeContainer.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import * as React from "react"; -import { Home } from "./Home"; -import { ILicense } from "./interfaces/ILicense"; -import { IList } from "./interfaces/IList"; -import { IMaintainer } from "./interfaces/IMaintainer"; -import { ISoftware } from "./interfaces/ISoftware"; -import { ISyntax } from "./interfaces/ISyntax"; -import { ITag } from "./interfaces/ITag"; -import { Language } from "./interfaces/Language"; - -interface IState { - languages: Language[]; - licenses: ILicense[]; - lists: IList[]; - maintainers: IMaintainer[]; - ruleCount: number; - software: ISoftware[]; - syntaxes: ISyntax[]; - tags: ITag[]; -}; - -export class HomeContainer extends React.Component<{}, IState> { - constructor(props: any) { - super(props); - this.state = { - languages: [], - licenses: [], - lists: [], - maintainers: [], - ruleCount: 0, - software: [], - syntaxes: [], - tags: [] - }; - } - - componentDidMount() { - this.fetchLists(); - this.fetchLanguages(); - this.fetchLicenses(); - this.fetchMaintainers(); - this.fetchSoftware(); - this.fetchSyntaxes(); - this.fetchTags(); - }; - - fetchLanguages() { - fetch("/api/v1/languages") - .then(response => response.json()) - .then(json => { this.setState({ languages: json }); }) - }; - - fetchLicenses() { - fetch("/api/v1/licenses") - .then(response => response.json()) - .then(json => { this.setState({ licenses: json }); }) - }; - - fetchLists() { - fetch("/api/v1/lists") - .then(response => response.json()) - .then(json => { this.setState({ lists: json }); }) - }; - - fetchMaintainers() { - fetch("/api/v1/maintainers") - .then(response => response.json()) - .then(json => { this.setState({ maintainers: json }); }) - }; - - fetchSoftware() { - fetch("/api/v1/software") - .then(response => response.json()) - .then(json => { this.setState({ software: json }); }) - }; - - fetchSyntaxes() { - fetch("/api/v1/syntaxes") - .then(response => response.json()) - .then(json => { this.setState({ syntaxes: json }); }) - }; - - fetchTags() { - fetch("/api/v1/tags") - .then(response => response.json()) - .then(json => { this.setState({ tags: json }); }) - }; - - render() { - return ; - }; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/IListDetails.ts b/src/FilterLists.Web/src/modules/home/components/IListDetails.ts deleted file mode 100644 index d5ed31f82..000000000 --- a/src/FilterLists.Web/src/modules/home/components/IListDetails.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ILicense } from "../interfaces/ILicense"; -import { IMaintainer } from "../interfaces/IMaintainer"; -import { ISyntax } from "../interfaces/ISyntax"; -import { ITag } from "../interfaces/ITag"; -import { Language } from "../interfaces/Language"; - -export interface IListDetails { - id: number; - chatUrl: string; - description: string; - descriptionSourceUrl: string; - donateUrl: string; - emailAddress: string; - forumUrl: string; - homeUrl: string; - issuesUrl: string; - languages: Language[]; - license: ILicense; - maintainers: IMaintainer[]; - name: string; - policyUrl: string; - publishedDate: string; - submissionUrl: string; - syntax: ISyntax; - tags: ITag[]; - viewUrl: string; - viewUrlMirrors: string[]; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/Oneliner.tsx b/src/FilterLists.Web/src/modules/home/components/Oneliner.tsx deleted file mode 100644 index b9754c39f..000000000 --- a/src/FilterLists.Web/src/modules/home/components/Oneliner.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; - -interface Props { - listCount: number; -}; - -export const Oneliner = (props: Props) => - props.listCount > 0 - ?

- The independent, comprehensive directory of {props.listCount.toLocaleString()} filter and host lists for advertisements, trackers, malware, and annoyances. -

- :

- The independent, comprehensive directory of filter and host lists for advertisements, trackers, malware, and annoyances. -

; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/TagGroup.tsx b/src/FilterLists.Web/src/modules/home/components/TagGroup.tsx deleted file mode 100644 index a6439ab80..000000000 --- a/src/FilterLists.Web/src/modules/home/components/TagGroup.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import * as React from "react"; -import { getContrast } from "../../../utils"; -import { ITag } from "../interfaces/ITag"; - -interface Props { - tags: ITag[]; -}; - -export const TagGroup = (props: Props) => - props.tags && props.tags.length > 0 - ?
- {props.tags.map((t: ITag, i: number) => )} -
- : null; - -interface ITagProps { - tag: ITag; -}; - -const Tag = (props: ITagProps) => { - if (props.tag) { - const hexColor = kelly_colors_hex[props.tag.id % kelly_colors_hex.length]; - return - {props.tag.name} - ; - } else { - return null; - } -}; - -//https://stackoverflow.com/a/4382138/2343739 -const kelly_colors_hex = [ - "FFB300", // Vivid Yellow - "803E75", // Strong Purple - "FF6800", // Vivid Orange - "A6BDD7", // Very Light Blue - "C10020", // Vivid Red - "CEA262", // Grayish Yellow - "817066", // Medium Gray - "007D34", // Vivid Green - "F6768E", // Strong Purplish Pink - "00538A", // Strong Blue - "FF7A5C", // Strong Yellowish Pink - "53377A", // Strong Violet - "FF8E00", // Vivid Orange Yellow - "B32851", // Strong Purplish Red - "F4C800", // Vivid Greenish Yellow - "7F180D", // Strong Reddish Brown - "93AA00", // Vivid Yellowish Green - "593315", // Deep Yellowish Brown - "F13A13", // Vivid Reddish Orange - "232C16", // Dark Olive Green - "000000", // Black - "FFFFFF", // White - "C2F4BE", // Light Green - "1EDBB9", // Medium Greenish Blue - "890000", // Dark Red - "474747", // Dark Grey - "BFA125", // Matte Gold - "A7823C", // Dark Beige - "035A5C" // Dark Greenish Blue -]; diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/DetailsExpander.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/DetailsExpander.tsx deleted file mode 100644 index 54c7002be..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/DetailsExpander.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from "react"; -import { IColumnVisibility } from "../../interfaces/IColumnVisibility"; -import { ISoftware } from "../../interfaces/ISoftware"; -import { IListDetails } from "../IListDetails"; -import { InfoCard } from "./infoCard"; -import { LinkButtonGroup } from "./LinkButtonGroup"; -import { MaintainersInfoCard } from "./maintainersInfoCard"; - -interface Props { - columnVisibility: IColumnVisibility[]; - list: IListDetails; - software: ISoftware[]; -}; - -export const DetailsExpander = (props: Props) => -
-
-
-
- - -
-
- -
-
-
-
; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/LinkButtonGroup.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/LinkButtonGroup.tsx deleted file mode 100644 index 5049b2026..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/LinkButtonGroup.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from "react"; -import { ChatButton, DonateButton, EmailButton, ForumButton, HomeButton, IssuesButton, PolicyButton, SubmitButton, SubscribeButton, ViewButton } from "../linkButtons"; -import "./linkButtonGroup.css"; - -interface Props { - chatUrl: string; - donateUrl: string; - emailAddress: string; - forumUrl: string; - homeUrl: string; - issuesUrl: string; - name: string; - policyUrl: string; - submissionUrl: string; - viewUrl: string; - viewUrlMirrors: string[]; -}; - -export const LinkButtonGroup = (props: Props) => -
- - - - - - - - - - -
; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/index.ts b/src/FilterLists.Web/src/modules/home/components/detailsExpander/index.ts deleted file mode 100644 index 741dbb60b..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { DetailsExpander } from "./DetailsExpander"; - -export { DetailsExpander }; diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Description.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Description.tsx deleted file mode 100644 index 93a782295..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Description.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from "react"; -import "./description.css"; - -interface Props { - description: string; - url: string; -}; - -export const Description = (props: Props) => - props.description - ?

- {props.url - ?
{props.description}
- : props.description} -

- : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/InfoCard.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/InfoCard.tsx deleted file mode 100644 index fd52dac1f..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/InfoCard.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import * as React from "react"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; -import { ILicense } from "../../../interfaces/ILicense"; -import { ISoftware } from "../../../interfaces/ISoftware"; -import { ISyntax } from "../../../interfaces/ISyntax"; -import { ITag } from "../../../interfaces/ITag"; -import { Language } from "../../../interfaces/Language"; -import { SoftwareIcon } from "../../softwareIcon"; -import { TagGroup } from "../../TagGroup"; -import { Description } from "./Description"; -import { Languages } from "./Languages"; -import { License } from "./License"; -import { PublishedDate } from "./PublishedDate"; -import { Syntax } from "./Syntax"; - -interface Props { - columnVisibility: IColumnVisibility[]; - description: string; - descriptionSourceUrl: string; - languages: Language[]; - license: ILicense; - name: string; - publishedDate: string; - software: ISoftware[]; - syntax: ISyntax; - tags: ITag[]; -}; - -export const InfoCard = (props: Props) => -
- {props.columnVisibility.filter((c: IColumnVisibility) => c.column === "Tags")[0].visible - ? null - : } -
- {props.columnVisibility.filter((c: IColumnVisibility) => c.column === "Software")[0].visible - ? null - : props.syntax - ? props.software.filter((s: ISoftware) => s.syntaxIds.indexOf(props.syntax.id) > -1) - .map((s: ISoftware, i: number) => ) - : null} -
- -
    - - - - {props.columnVisibility.filter((c: IColumnVisibility) => c.column === "License")[0].visible - ? null - : } -
-
; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Languages.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Languages.tsx deleted file mode 100644 index cb3989273..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Languages.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from "react"; -import { Language } from "../../../interfaces/Language"; - -interface Props { - languages: Language[]; -}; - -export const Languages = (props: Props) => - props.languages && props.languages.length > 0 - ? props.languages.length > 1 - ?
  • -

    Languages:

    -
      - {props.languages.map((language: Language, i: number) =>
    • {language.name}
    • )} -
    -
  • - :
  • -

    Language: {props.languages[0].name}

    -
  • - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/License.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/License.tsx deleted file mode 100644 index 0c2c51776..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/License.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from "react"; -import { ILicense } from "../../../interfaces/ILicense"; - -interface Props { - license: ILicense; -}; - -export const License = (props: Props) => - props.license.name - ? (props.license.descriptionUrl - ?
  • -

    License: {props.license.name}

    -
  • - :
  • -

    License: {props.license.name}

    -
  • ) - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/PublishedDate.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/PublishedDate.tsx deleted file mode 100644 index 67325b70a..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/PublishedDate.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import moment from 'moment'; -import * as React from "react"; - -interface Props { - date: string; -}; - -export const PublishedDate = (props: Props) => - props.date - ?
  • -

    Published: {moment(props.date).format("l")}

    -
  • - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/RuleCount.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/RuleCount.tsx deleted file mode 100644 index 1d57aeb87..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/RuleCount.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import * as React from "react"; - -interface Props { - ruleCount: number; -}; - -export const RuleCount = (props: Props) => - props.ruleCount > 0 - ?
  • -

    Rule Count: {props.ruleCount.toLocaleString()}

    -
  • - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Syntax.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Syntax.tsx deleted file mode 100644 index 473590ff3..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/Syntax.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from "react"; -import { ISyntax } from "../../../interfaces/ISyntax"; - -interface Props { - syntax: ISyntax; -}; - -export const Syntax = (props: Props) => - props.syntax - ? (props.syntax.definitionUrl - ?
  • -

    Syntax: {props.syntax.name}

    -
  • - :
  • -

    Syntax: {props.syntax.name}

    -
  • ) - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/UpdatedDate.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/UpdatedDate.tsx deleted file mode 100644 index 7ccd41bb1..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/UpdatedDate.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import moment from 'moment'; -import * as React from "react"; - -interface Props { - updatedDate: string; -}; - -export const UpdatedDate = (props: Props) => - props.updatedDate - ?
  • -

    Updated: {moment(props.updatedDate).isValid() - ? moment(props.updatedDate).format("l") - : "N/A"}

    -
  • - : null; diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/description.css b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/description.css deleted file mode 100644 index 2a1267485..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/description.css +++ /dev/null @@ -1 +0,0 @@ -.fl-description { margin: 0 0 .5rem; } \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/index.ts b/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/index.ts deleted file mode 100644 index 260aed18f..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/infoCard/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { InfoCard } from "./InfoCard"; - -export { InfoCard }; diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/linkButtonGroup.css b/src/FilterLists.Web/src/modules/home/components/detailsExpander/linkButtonGroup.css deleted file mode 100644 index a590b0139..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/linkButtonGroup.css +++ /dev/null @@ -1,3 +0,0 @@ -.btn-group-vertical { - display: inline; -} diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainerInfoCard.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainerInfoCard.tsx deleted file mode 100644 index d773bc9b5..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainerInfoCard.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from "react"; -import { IMaintainer } from "../../../interfaces/IMaintainer"; -import { MaintainerLinkButtonGroup } from "./MaintainerLinkButtonGroup"; - -interface Props { - maintainer: IMaintainer; -}; - -export const MaintainerInfoCard = (props: Props) => - props.maintainer.name - ?
    -
    -

    Maintained by {props.maintainer.name}

    -
    -
    - -
    -
    -
    -
    - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainerLinkButtonGroup.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainerLinkButtonGroup.tsx deleted file mode 100644 index e8afa1c2c..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainerLinkButtonGroup.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from "react"; -import { EmailButton, HomeButton, TwitterButton } from "../../linkButtons"; - -interface Props { - emailAddress: string; - homeUrl: string; - name: string; - twitterHandle: string; -}; - -export const MaintainerLinkButtonGroup = (props: Props) => -
    - - - -
    ; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainersInfoCard.tsx b/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainersInfoCard.tsx deleted file mode 100644 index dc31c5772..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/MaintainersInfoCard.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { IMaintainer } from "../../../interfaces/IMaintainer"; -import { MaintainerInfoCard } from "./MaintainerInfoCard"; - -interface Props { - maintainers: IMaintainer[]; -}; - -export const MaintainersInfoCard = (props: Props) => - props.maintainers && props.maintainers.length > 0 - ?
    - {props.maintainers.map((m: IMaintainer, i: number) => )} -
    - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/index.ts b/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/index.ts deleted file mode 100644 index 162aa5359..000000000 --- a/src/FilterLists.Web/src/modules/home/components/detailsExpander/maintainersInfoCard/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { MaintainersInfoCard } from "./MaintainersInfoCard"; - -export { MaintainersInfoCard }; diff --git a/src/FilterLists.Web/src/modules/home/components/index.ts b/src/FilterLists.Web/src/modules/home/components/index.ts deleted file mode 100644 index feee39ff4..000000000 --- a/src/FilterLists.Web/src/modules/home/components/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { DetailsExpander } from "./detailsExpander"; -import { ListsTable } from "./listsTable"; -import { Oneliner } from "./Oneliner"; - -export { DetailsExpander, ListsTable, Oneliner }; diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/ChatButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/ChatButton.tsx deleted file mode 100644 index 573a4a1b3..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/ChatButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - url: string; -}; - -export const ChatButton = (props: Props) => - props.url - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/DonateButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/DonateButton.tsx deleted file mode 100644 index 8ac2711a1..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/DonateButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - url: string; -}; - -export const DonateButton = (props: Props) => - props.url - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/EmailButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/EmailButton.tsx deleted file mode 100644 index 0b7e6f8bc..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/EmailButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - emailAddress: string; -}; - -export const EmailButton = (props: Props) => - props.emailAddress - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/ForumButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/ForumButton.tsx deleted file mode 100644 index 756bcef71..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/ForumButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - url: string; -}; - -export const ForumButton = (props: Props) => - props.url - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/HomeButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/HomeButton.tsx deleted file mode 100644 index d9add0cb2..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/HomeButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - url: string; -}; - -export const HomeButton = (props: Props) => - props.url - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/IssuesButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/IssuesButton.tsx deleted file mode 100644 index 8b00c10ee..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/IssuesButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - url: string; -}; - -export const IssuesButton = (props: Props) => - props.url - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/LinkButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/LinkButton.tsx deleted file mode 100644 index a8a003a71..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/LinkButton.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from "react"; -import { Button, ButtonProps } from "react-bootstrap"; - -interface Props { - href: string; - variant?: ButtonProps["variant"], - title?: string; - text: string; -}; - -export const LinkButton = (props: Props) => - props.href - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/PolicyButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/PolicyButton.tsx deleted file mode 100644 index 0107e7200..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/PolicyButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - url: string; -}; - -export const PolicyButton = (props: Props) => - props.url - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubmitButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/SubmitButton.tsx deleted file mode 100644 index 2de8de818..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubmitButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - url: string; -}; - -export const SubmitButton = (props: Props) => - props.url - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButton.tsx deleted file mode 100644 index 67e19c951..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButton.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import * as React from "react"; -import { ButtonProps } from "react-bootstrap"; -import { LinkButton } from "../LinkButton"; - -interface Props { - name: string; - url: string; - text?: string; -}; - -export const SubscribeButton = (props: Props) => { - let buttonVariant: ButtonProps["variant"]; - let titlePrefix: string; - - if (props.url.indexOf(".onion/") > 0) { - buttonVariant = "success"; - titlePrefix = "Tor address - "; - } else if (props.url.indexOf("http://") === 0) { - buttonVariant = "danger"; - titlePrefix = "Not Secure - "; - } else { - buttonVariant = undefined; - titlePrefix = ""; - } - - const hrefTitle = `${encodeURIComponent(props.name)}`; - let href; - if (props.url.indexOf(".tpl") > 0) { - href = `javascript:window.external.msAddTrackingProtectionList('${encodeURIComponent(props.url)}', '${hrefTitle}')`; - } else if (props.url.indexOf(".lsrules") > 0) { - href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.url)}`; - } else if (props.url.indexOf("?hostformat=littlesnitch") > 0) { - href = `x-littlesnitch:subscribe-rules?url=${encodeURIComponent(props.url)}`; - } else { - href = `abp:subscribe?location=${encodeURIComponent(props.url)}&title=${hrefTitle}`; - }; - - let title; - if (props.url.indexOf(".tpl") > 0) { - title = `${titlePrefix}Subscribe to ${props.name} with Internet Explorer's Tracking Protection List feature.`; - } else if (props.url.indexOf(".lsrules") > 0) { - title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; - } else if (props.url.indexOf("?hostformat=littlesnitch") > 0) { - title = `${titlePrefix}Subscribe to ${props.name} with Little Snitch's rule group subscription feature.`; - } else { - title = `${titlePrefix}Subscribe to ${props.name} with a browser extension supporting the "abp:" protocol (e.g. uBlock Origin, Adblock Plus).`; - }; - - return props.url - ? - : null; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButtonGroup.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButtonGroup.tsx deleted file mode 100644 index 5e876d6c3..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButtonGroup.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from "react"; -import { SubscribeButton } from "./SubscribeButton"; -import { SubscribeButtonGroupDropdown } from "./SubscribeButtonGroupDropdown"; - -interface Props { - name: string; - url: string; - urlMirrors?: string[]; -}; - -export const SubscribeButtonGroup = (props: Props) => - props.url - ? (props.urlMirrors && props.urlMirrors.length > 0) - ? - : - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButtonGroupDropdown.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButtonGroupDropdown.tsx deleted file mode 100644 index 922c9a5e2..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/SubscribeButtonGroupDropdown.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from "react"; -import { Dropdown, DropdownButton } from "react-bootstrap"; -import { SubscribeButton } from "./SubscribeButton"; - -interface Props { - name: string; - url: string; - urlMirrors: string[]; -}; - -export const SubscribeButtonGroupDropdown = (props: Props) => { - let firstButtonText: string = "Original"; - let mirrorIndex: number = 0; - - if (props.url.indexOf("web.archive.org") !== -1) { - firstButtonText = "Mirror 1"; - mirrorIndex++; - } - - return - - - - {props.urlMirrors.map( - (m: string, i: number) => - - - )} - ; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/index.ts b/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/index.ts deleted file mode 100644 index 870bea9c7..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/SubscribeButton/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { SubscribeButtonGroup } from "./SubscribeButtonGroup"; - -export { SubscribeButtonGroup as SubscribeButton }; diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/TwitterButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/TwitterButton.tsx deleted file mode 100644 index e632dc519..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/TwitterButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "./LinkButton"; - -interface Props { - name: string; - twitterHandle: string; -}; - -export const TwitterButton = (props: Props) => - props.twitterHandle - ? - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButton.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButton.tsx deleted file mode 100644 index 221238fdd..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButton.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from "react"; -import { LinkButton } from "../LinkButton"; - -interface Props { - name: string; - url: string; - text?: string; -}; - -export const ViewButton = (props: Props) => { - - let title; - if (props.url.indexOf(".onion/") > 0) { title = `Tor address - View ${props.name} in its raw format.`; } - else if (props.url.indexOf(".zip") > 0) { title = `Download ${props.name} as a ZIP compressed archive.`; } - else if (props.url.indexOf(".7z") > 0) { title = `Download ${props.name} as a 7Z compressed archive.`; } - else if (props.url.indexOf(".tar.gz") > 0) { title = `Download ${props.name} as a compressed tarball archive.`; } - else { title = `View ${props.name} in its raw format`; }; - - return props.url - ? - : null; -} diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButtonGroup.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButtonGroup.tsx deleted file mode 100644 index adc0cb388..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButtonGroup.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from "react"; -import { ViewButton } from "./ViewButton"; -import { ViewButtonGroupDropdown } from "./ViewButtonGroupDropdown"; - -interface Props { - name: string; - url: string; - urlMirrors?: string[]; -}; - -export const ViewButtonGroup = (props: Props) => - props.url - ? (props.urlMirrors && props.urlMirrors.length > 0) - ? - : - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButtonGroupDropdown.tsx b/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButtonGroupDropdown.tsx deleted file mode 100644 index a72a6cece..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/ViewButtonGroupDropdown.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from "react"; -import { Dropdown, DropdownButton } from "react-bootstrap"; -import { ViewButton } from "./ViewButton"; - -interface Props { - name: string; - url: string; - urlMirrors: string[]; -}; - -export const ViewButtonGroupDropdown = (props: Props) => { - let firstButtonText: string = "Original"; - let mirrorIndex: number = 0; - - if (props.url.indexOf("web.archive.org") !== -1) { - firstButtonText = "Mirror 1"; - mirrorIndex++; - } - - return - - - - {props.urlMirrors.map( - (m: string, i: number) => - - - )} - ; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/index.ts b/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/index.ts deleted file mode 100644 index 6a15392f2..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/ViewButton/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ViewButtonGroup } from "./ViewButtonGroup"; - -export { ViewButtonGroup as ViewButton }; diff --git a/src/FilterLists.Web/src/modules/home/components/linkButtons/index.ts b/src/FilterLists.Web/src/modules/home/components/linkButtons/index.ts deleted file mode 100644 index 15e7c38f1..000000000 --- a/src/FilterLists.Web/src/modules/home/components/linkButtons/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ChatButton } from "./ChatButton"; -import { DonateButton } from "./DonateButton"; -import { EmailButton } from "./EmailButton"; -import { ForumButton } from "./ForumButton"; -import { HomeButton } from "./HomeButton"; -import { IssuesButton } from "./IssuesButton"; -import { PolicyButton } from "./PolicyButton"; -import { SubmitButton } from "./SubmitButton"; -import { SubscribeButton } from "./SubscribeButton"; -import { TwitterButton } from "./TwitterButton"; -import { ViewButton } from "./ViewButton"; - -export { ChatButton, DonateButton, EmailButton, ForumButton, HomeButton, IssuesButton, PolicyButton, SubmitButton, SubscribeButton, TwitterButton, ViewButton }; diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/ListsTable.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/ListsTable.tsx deleted file mode 100644 index 3816e7c1f..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/ListsTable.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import * as React from "react"; -import ReactTable from "react-table"; -import "react-table/react-table.css"; -import "../../../../utils/loader.css"; -import { DetailsExpander } from "../../components"; -import { IColumnVisibility } from "../../interfaces/IColumnVisibility"; -import { ILicense } from "../../interfaces/ILicense"; -import { IList } from "../../interfaces/IList"; -import { IMaintainer } from "../../interfaces/IMaintainer"; -import { ISoftware } from "../../interfaces/ISoftware"; -import { ISyntax } from "../../interfaces/ISyntax"; -import { ITag } from "../../interfaces/ITag"; -import { Language } from "../../interfaces/Language"; -import { IListDetails } from "../IListDetails"; -import { DetailsButton, Languages, License, Maintainers, Name, Software, SubscribeButton, Tags } from "./columns"; -import "./listsTable.css"; - -interface Props { - languages: Language[]; - licenses: ILicense[]; - lists: IList[]; - maintainers: IMaintainer[]; - software: ISoftware[]; - syntaxes: ISyntax[]; - tags: ITag[]; - columnVisibility: IColumnVisibility[]; - pageSize: number; -}; - -export const ListsTable = (props: Props) => - props.languages.length > 0 && props.lists.length > 0 && props.software.length > 0 && props.tags.length > 0 - ? - } - className="-striped -highlight" /> - :
    Loading...
    ; - -interface ICreateListDtoProps { - list: IList; - languages: Language[]; - licenses: ILicense[]; - maintainers: IMaintainer[]; - syntaxes: ISyntax[]; - tags: ITag[]; -}; - -const mapListDetails = (props: ICreateListDtoProps): IListDetails => - ({ - id: props.list.id, - chatUrl: props.list.chatUrl, - description: props.list.description, - descriptionSourceUrl: props.list.descriptionSourceUrl, - donateUrl: props.list.donateUrl, - emailAddress: props.list.emailAddress, - forumUrl: props.list.forumUrl, - homeUrl: props.list.homeUrl, - issuesUrl: props.list.issuesUrl, - languages: props.list.languageIds - ? props.languages.filter((l: Language) => props.list.languageIds.indexOf(l.id) > -1) - : undefined, - license: props.licenses.filter((l: ILicense) => props.list.licenseId === l.id)[0], - maintainers: props.list.maintainerIds - ? props.maintainers.filter((m: IMaintainer) => props.list.maintainerIds.indexOf(m.id) > -1) - : undefined, - name: props.list.name, - policyUrl: props.list.policyUrl, - publishedDate: props.list.publishedDate, - submissionUrl: props.list.submissionUrl, - syntax: props.syntaxes.filter((s: ISyntax) => props.list.syntaxId === s.id)[0], - tags: props.list.tagIds ? props.tags.filter((t: ITag) => props.list.tagIds.indexOf(t.id) > -1) : undefined, - viewUrl: props.list.viewUrl, - viewUrlMirrors: props.list.viewUrlMirrors - } as IListDetails); \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/DetailsButton.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/DetailsButton.tsx deleted file mode 100644 index e72c23aff..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/DetailsButton.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from "react"; -import { Button } from "react-bootstrap"; -import { Column, RowRenderProps } from "react-table"; - -export const DetailsButton = { - Header: Details, - accessor: "id", - sortable: false, - expander: true, - Expander: ({ isExpanded, row }: RowRenderProps) => Expander({ isExpanded, row }), - style: { textAlign: "center" }, - width: 110 -} as Column; - -const Expander = (props: RowRenderProps) => -
    - {props.isExpanded - ? - : } -
    ; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Languages.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Languages.tsx deleted file mode 100644 index 6d8a1e782..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Languages.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import * as React from "react"; -import { Column, Filter } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; -import { Language } from "../../../interfaces/Language"; - -export const Languages = (columnVisibility: IColumnVisibility[], languages: Language[]) => { - const languagesSorted = languages.sort((a, b) => a.name.localeCompare(b.name)); - return ({ - Header: Languages, - accessor: "languageIds", - filterable: true, - filterMethod: (f: Filter, r: any[]) => filterMethod(f, r), - Filter: ({ onChange, filter }: any) => filterLanguages({ onChange, filter }, languagesSorted), - sortMethod: (a: number[], b: number[]) => sortMethod(a, b, languagesSorted), - Cell: (c: any) => Cell(c.value, languagesSorted), - style: { whiteSpace: "inherit" }, - width: 95, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Languages")[0].visible - } as Column); -}; - -const filterMethod = (f: Filter, r: any[]): boolean => { - const listLanguageIds = r[f.id as any]; - return f.value === "any" || - (listLanguageIds - ? listLanguageIds.join(",").split(",").includes(f.value) - : f.value === "none"); -}; - -const filterLanguages = (props: any, languages: Language[]) => - ; - -const sortMethod = (a: number[], b: number[], languages: Language[]) => { - if (a && a.length > 0) { - if (b && b.length > 0) { - const aLanguageNames = - languages.filter((l: Language) => a.indexOf(l.id) > -1).map((l: Language) => l.name).join(); - const bLanguageNames = - languages.filter((l: Language) => b.indexOf(l.id) > -1).map((l: Language) => l.name).join(); - return aLanguageNames.toLowerCase() > bLanguageNames.toLowerCase() ? 1 : -1; - } else { - return -1; - } - } else { - return 1; - } -}; - -const Cell = (languageIds: number[], languages: Language[]) => - languageIds - ?
    - {languageIds.map((id: number, i: number) => { - const language = languages.filter((l: Language) => l.id === id)[0]; - return - {language.iso6391} - ; - })} -
    - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/License.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/License.tsx deleted file mode 100644 index 84a221b35..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/License.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import * as React from "react"; -import { Column, Filter } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; -import { ILicense } from "../../../interfaces/ILicense"; - -export const License = (columnVisibility: IColumnVisibility[], licenses: ILicense[]) => - ({ - Header: License, - accessor: "licenseId", - filterable: true, - filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, licenses), - Filter: ({ filter, onChange }: any) => filterLicenses({ onChange, filter }, licenses), - sortMethod: (a: number, b: number) => sortMethod(a, b, licenses), - Cell: (c: any) => Cell(c.value, licenses), - width: 75, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "License")[0].visible - } as Column); - -const filterMethod = (f: Filter, r: any[], licenses: ILicense[]): boolean => { - const listLicenseId: number = r[f.id as any]; - if (f.value === "any") { - return true; - } else if (listLicenseId) { - const licenseFiltered = licenses.filter((l: ILicense) => l.id === parseInt(f.value))[0]; - return listLicenseId === licenseFiltered.id; - } else { - return false; - } -}; - -const filterLicenses = (props: any, licenses: ILicense[]) => - ; - -const sortMethod = (a: number, b: number, licenses: ILicense[]) => { - if (a) { - if (b) { - const aLicenseName = licenses.filter((l: ILicense) => l.id === a)[0].name.replace(/['"]+/g, ""); - const bLicenseName = licenses.filter((l: ILicense) => l.id === b)[0].name.replace(/['"]+/g, ""); - return aLicenseName.toLowerCase() > bLicenseName.toLowerCase() ? 1 : -1; - } else { - return -1; - } - } else { - return 1; - } -}; - -const Cell = (licenseId: number, licenses: ILicense[]) => { - const license = licenses.filter((l: ILicense) => licenseId === l.id)[0]; - return license - ?
    - - {license.descriptionUrl ? {license.name} : license.name} - -
    - : null; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Maintainers.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Maintainers.tsx deleted file mode 100644 index 029e05318..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Maintainers.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import * as React from "react"; -import { Column, Filter } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; -import { IMaintainer } from "../../../interfaces/IMaintainer"; - -export const Maintainers = (columnVisibility: IColumnVisibility[], maintainers: IMaintainer[]) => - ({ - Header: Maintainers, - accessor: "maintainerIds", - filterable: true, - filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, maintainers), - Filter: ({ filter, onChange }: any) => filterMaintainers({ onChange, filter }, maintainers), - sortMethod: (a: number[], b: number[]) => sortMethod(a, b, maintainers), - Cell: (c: any) => Cell(c.value, maintainers), - width: 140, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Maintainers")[0].visible - } as Column); - -const filterMethod = (f: Filter, r: any[], maintainers: IMaintainer[]): boolean => { - const listMaintainerIds: number[] = r[f.id as any]; - return f.value === "any" || - (listMaintainerIds - ? f.value === "none" - ? false - : listMaintainerIds.indexOf(maintainers.filter((m: IMaintainer) => m.id === parseInt(f.value))[0].id) > -1 - : f.value === "none"); -}; - -const filterMaintainers = (props: any, maintainers: IMaintainer[]) => - ; - -const sortMethod = (a: number[], b: number[], maintainers: IMaintainer[]) => { - if (a && a.length > 0) { - if (b && b.length > 0) { - const aFirstMaintainerName = maintainers.filter((m: IMaintainer) => m.id === a[0])[0].name; - const bFirstMaintainerName = maintainers.filter((m: IMaintainer) => m.id === b[0])[0].name; - return aFirstMaintainerName.toLowerCase() > bFirstMaintainerName.toLowerCase() ? 1 : -1; - } else { - return -1; - } - } else { - return 1; - } -}; - -const Cell = (maintainerIds: number[], maintainers: IMaintainer[]) => - maintainerIds - ?
    - {maintainers.filter((m: IMaintainer) => maintainerIds.indexOf(m.id) > -1) - .map((m: IMaintainer, i: number) => { - return m.homeUrl - ? {m.name} - : {m.name}; - }).reduce(((prev: JSX.Element, curr: JSX.Element): any => [prev, ", ", curr]) as any)} -
    - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Name.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Name.tsx deleted file mode 100644 index ab74d9497..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Name.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from "react"; -import { Column, Filter } from "react-table"; - -export const Name = { - Header: Name, - accessor: "name", - filterable: true, - filterMethod: (f: Filter, r: any[]) => filterMethod(f, r), - sortMethod: (a: string, b: string) => sortMethod(a, b), - Cell: (c: any) => Cell(c.value) -} as Column; - -const filterMethod = (f: Filter, r: any[]): boolean => - r[f.id as any].toUpperCase().includes(f.value.toUpperCase()); - -const sortMethod = (a: string, b: string) => - a.toLowerCase() > b.toLowerCase() ? 1 : -1; - -const Cell = (name: string) => - name - ?

    {name}

    - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/RuleCount.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/RuleCount.tsx deleted file mode 100644 index 90ee34b70..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/RuleCount.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from "react"; -import { Column } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; - -export const RuleCount = (columnVisibility: IColumnVisibility[]) => - ({ - Header: Rules, - accessor: "ruleCount", - sortMethod: (a: string, b: string) => sortMethod(a, b), - Cell: (c: any) => Cell(c.value), - style: { whiteSpace: "inherit" }, - width: 85, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Rules")[0].visible - } as Column); - -const sortMethod = (a: string, b: string) => - a - ? b - ? a > b - ? -1 - : 1 - : -1 - : 1; - -const Cell = (ruleCount: number) => - ruleCount - ? {ruleCount.toLocaleString()} - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Software.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Software.tsx deleted file mode 100644 index 8644ea981..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Software.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import * as React from "react"; -import { Column, Filter } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; -import { ISoftware } from "../../../interfaces/ISoftware"; -import { SoftwareIcon } from "../../softwareIcon"; - -export const Software = (columnVisibility: IColumnVisibility[], software: ISoftware[]) => { - const softwareSorted = software.sort((a, b) => a.name.localeCompare(b.name)); - return ({ - Header: - Software, - accessor: "syntaxId", - filterable: true, - filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, softwareSorted), - Filter: ({ filter, onChange }: any) => filterSoftware({ onChange, filter }, softwareSorted), - sortMethod: (a: number, b: number) => sortMethod(a, b, softwareSorted), - Cell: (c: any) => Cell(c.value, software), - width: 155, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Software")[0].visible - } as Column); -}; - -const filterMethod = (f: Filter, r: any[], software: ISoftware[]): boolean => { - const isAny = f.value === "any"; - const softwareFiltered = isAny ? software : software.filter((s: ISoftware) => s.id === parseInt(f.value)); - const listSyntaxId: number = r[f.id as any]; - const isMatch = softwareFiltered[0].syntaxIds ? softwareFiltered[0].syntaxIds.indexOf(listSyntaxId) > -1 : false; - return isAny || (listSyntaxId ? isMatch : false); -}; - -const filterSoftware = (props: any, software: ISoftware[]) => - ; - -const sortMethod = (a: number, b: number, software: ISoftware[]) => { - if (a) { - if (b) { - const aSoftwareNames = - software.filter((s: ISoftware) => s.syntaxIds.indexOf(a) > -1).map((s: ISoftware) => s.name); - const bSoftwareNames = - software.filter((s: ISoftware) => s.syntaxIds.indexOf(b) > -1).map((s: ISoftware) => s.name); - if (aSoftwareNames.length === bSoftwareNames.length) { - return aSoftwareNames.join().toLowerCase() > bSoftwareNames.join().toLowerCase() ? 1 : -1; - } else if (aSoftwareNames.length > bSoftwareNames.length) { - return -1; - } else { - return 1; - } - } else { - return -1; - } - } else { - return 1; - } -}; - -const Cell = (listSyntaxId: number, software: ISoftware[]) => - listSyntaxId - ?
    - {software.filter((s: ISoftware) => s.syntaxIds.indexOf(listSyntaxId) > -1) - .map((s: ISoftware, i: number) => - s.homeUrl - ? - - - : )} -
    - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/SubscribeButton.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/SubscribeButton.tsx deleted file mode 100644 index 42e89260b..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/SubscribeButton.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from "react"; -import { Column, Filter } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; -import { SubscribeButton as SubscribeButtonBase } from "../../linkButtons"; - -export const SubscribeButton = (columnVisibility: IColumnVisibility[]) => ({ - Header: - Subscribe - , - accessor: "viewUrl", - filterable: true, - filterMethod: (f: Filter, r: any[]) => filterMethod(f, r), - sortMethod: (a: string, b: string) => sortMethod(a, b), - Cell: (c: any) => , - style: { textAlign: "center" }, - width: 110, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Subscribe")[0].visible -} as Column); - -const filterMethod = (f: Filter, r: any[]): boolean => - r[f.id as any].toUpperCase().includes(f.value.toUpperCase()); - -const sortMethod = (a: string, b: string) => - a.toLowerCase() > b.toLowerCase() ? 1 : -1; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Syntax.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Syntax.tsx deleted file mode 100644 index 773e52cea..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Syntax.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import * as React from "react"; -import { Column, Filter } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; -import { ISyntax } from "../../../interfaces/ISyntax"; - -//TODO: https://github.com/collinbarrett/FilterLists/issues/488 -export const Syntax = (columnVisibility: IColumnVisibility[], syntaxes: ISyntax[]) => ({ - Header: Syntax, - accessor: "syntaxId", - filterable: true, - filterMethod: (f: Filter, r: any[]) => filterMethod(f, r, syntaxes), - Filter: ({ filter, onChange }: any) => filterSyntaxes({ onChange, filter }, syntaxes), - Cell: (c: any) => Cell(c.value, syntaxes), - width: 155, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Syntax")[0].visible -} as Column); - -const filterMethod = (f: Filter, r: any[], syntaxes: ISyntax[]): boolean => { - const listSyntaxId: number = r[f.id as any]; - if (f.value === "any") { - return true; - } else if (listSyntaxId) { - const syntaxFiltered = syntaxes.filter((s: ISyntax) => s.id === parseInt(f.value)); - return syntaxFiltered[0].id - ? syntaxFiltered[0].id === listSyntaxId - : false; - } else { - return false; - } -}; - -const filterSyntaxes = (props: any, syntaxes: ISyntax[]) => - ; - -const Cell = (listSyntaxId: number, syntaxes: ISyntax[]) => - listSyntaxId - ? syntaxes.filter((s: ISyntax) => s.id === listSyntaxId)[0].name - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Tags.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Tags.tsx deleted file mode 100644 index 76957a4e5..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/Tags.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import * as React from "react"; -import { Column, Filter } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; -import { ITag } from "../../../interfaces/ITag"; -import { TagGroup } from "../../TagGroup"; - -export const Tags = (columnVisibility: IColumnVisibility[], tags: ITag[]) => { - const tagsSorted = tags.sort((a: ITag, b: ITag) => a.name.localeCompare(b.name)); - return ({ - Header: - Tags, - accessor: "tagIds", - filterable: true, - filterMethod: (f: Filter, r: any[]) => filterMethod(f, r), - Filter: ({ onChange, filter }: any) => filterTags({ onChange, filter }, tagsSorted), - sortMethod: (a: number[], b: number[]) => sortMethod(a, b, tagsSorted), - Cell: (c: any) => Cell(c.value, tagsSorted), - width: 260, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Tags")[0].visible - } as Column); -}; - -const filterMethod = (f: Filter, r: any[]): boolean => { - const listTagIds = r[f.id as any]; - return f.value === "any" || - (listTagIds - ? listTagIds.join(",").split(",").includes(f.value) - : f.value === "none"); -}; - -const filterTags = (props: any, tags: ITag[]) => - ; - -const sortMethod = (a: number[], b: number[], tags: ITag[]): any => { - return a - ? b - ? a.length === b.length - ? tags.filter((t: ITag) => a.indexOf(t.id) > -1).map((t: ITag) => t.name).join() - .toLowerCase() > - tags.filter((t: ITag) => b.indexOf(t.id) > -1).map((t: ITag) => t.name).join().toLowerCase() - ? 1 - : -1 - : a.length > b.length - ? -1 - : 1 - : -1 - : 1; -}; - -const Cell = (tagIds: number[], tags: ITag[]) => - tagIds - ? tagIds.indexOf(t.id) > -1)} /> - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/UpdatedDate.tsx b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/UpdatedDate.tsx deleted file mode 100644 index 23acf2b89..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/UpdatedDate.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import moment from 'moment'; -import * as React from "react"; -import { Column } from "react-table"; -import { IColumnVisibility } from "../../../interfaces/IColumnVisibility"; - -export const UpdatedDate = (columnVisibility: IColumnVisibility[]) => - ({ - Header: Updated, - accessor: "updatedDate", - sortMethod: (a: string, b: string) => sortMethod(a, b), - Cell: (c: any) => Cell(c.value), - style: { whiteSpace: "inherit" }, - width: 100, - show: columnVisibility.filter((c: IColumnVisibility) => c.column === "Updated")[0].visible - } as Column); - -const sortMethod = (a: string, b: string) => - a && moment(a).isValid() - ? (b && moment(b).isValid() - ? (moment(a).isBefore(b) - ? 1 - : -1) - : -1) - : 1; - -const Cell = (updatedDate: string) => - updatedDate - ?
    - {moment(updatedDate).isValid() - ? moment(updatedDate).format("l") - : null} -
    - : null; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/index.ts b/src/FilterLists.Web/src/modules/home/components/listsTable/columns/index.ts deleted file mode 100644 index e82dc8aa9..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/columns/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { DetailsButton } from "./DetailsButton"; -import { Languages } from "./Languages"; -import { License } from "./License"; -import { Maintainers } from "./Maintainers"; -import { Name } from "./Name"; -import { RuleCount } from "./RuleCount"; -import { Software } from "./Software"; -import { SubscribeButton } from "./SubscribeButton"; -import { Syntax } from "./Syntax"; -import { Tags } from "./Tags"; -import { UpdatedDate } from "./UpdatedDate"; - -export { DetailsButton, Languages, License, Maintainers, Name, RuleCount, Software, SubscribeButton, Syntax, Tags, UpdatedDate }; diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/index.ts b/src/FilterLists.Web/src/modules/home/components/listsTable/index.ts deleted file mode 100644 index 6a848e986..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ListsTable } from "./ListsTable"; - -export { ListsTable, }; diff --git a/src/FilterLists.Web/src/modules/home/components/listsTable/listsTable.css b/src/FilterLists.Web/src/modules/home/components/listsTable/listsTable.css deleted file mode 100644 index 9315f2922..000000000 --- a/src/FilterLists.Web/src/modules/home/components/listsTable/listsTable.css +++ /dev/null @@ -1,16 +0,0 @@ -/* vertically center-align cell contents */ -.rt-tr { - -ms-align-items: center; - -o-align-items: center; - -webkit-align-items: center; - align-items: center; -} - -/* set minimum usable width of table */ -div.rt-tbody, div.rt-thead.-filters, div.rt-thead.-header { min-width: 320px !important; } - -/* prevent cell contents from getting trimmed */ -.fl-wrap-cell { - line-height: 1; - white-space: normal; -} \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/SoftwareIcon.tsx b/src/FilterLists.Web/src/modules/home/components/softwareIcon/SoftwareIcon.tsx deleted file mode 100644 index 8b7b94ec0..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/SoftwareIcon.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import * as React from "react"; -import { img1, img10, img11, img12, img13, img14, img15, img16, img17, img18, img19, img2, img20, img21, img22, img23, img24, img25, img26, img27, img28, img29, img3, img30, img31, img32, img33, img34, img4, img5, img6, img7, img8 } from "./imgs"; - -interface Props { - id: number; -}; - -export const SoftwareIcon = (props: Props) => - icons[props.id] - ? {icons[props.id].imageTitle} - : null; - -interface IIcon { - image: any; - imageTitle: string; -}; - -const icons: { [id: number]: IIcon; } = { - 1: { image: img1, imageTitle: "uBlock Origin" }, - 2: { image: img2, imageTitle: "Adblock Plus" }, - 3: { image: img3, imageTitle: "AdGuard" }, - 4: { image: img4, imageTitle: "DNS66" }, - 5: { image: img5, imageTitle: "Nano Adblocker" }, - 6: { image: img6, imageTitle: "AdBlock" }, - 7: { image: img7, imageTitle: "AdAway" }, - 8: { image: img8, imageTitle: "Personal Blocklist" }, - 10: { image: img10, imageTitle: "Redirector" }, - 11: { image: img11, imageTitle: "Hosts File Editor" }, - 12: { image: img12, imageTitle: "Gas Mask" }, - 13: { image: img13, imageTitle: "MinerBlock" }, - 14: { image: img14, imageTitle: "Pi-hole" }, - 15: { image: img15, imageTitle: "uBlock" }, - 16: { image: img16, imageTitle: "Internet Explorer (TPL)" }, - 17: { image: img17, imageTitle: "Google Hit Hider by Domain" }, - 18: { image: img18, imageTitle: "FireHOL" }, - 19: { image: img19, imageTitle: "Samsung Knox" }, - 20: { image: img20, imageTitle: "Little Snitch" }, - 21: { image: img21, imageTitle: "Privoxy" }, - 22: { image: img22, imageTitle: "Diversion" }, - 23: { image: img23, imageTitle: "dnsmasq" }, - 24: { image: img24, imageTitle: "Slimjet" }, - 25: { image: img25, imageTitle: "uMatrix" }, - 26: { image: img26, imageTitle: "Blokada" }, - 27: { image: img27, imageTitle: "hostsmgr" }, - 28: { image: img28, imageTitle: "personalDNSfilter" }, - 29: { image: img29, imageTitle: "Unbound" }, - 30: { image: img30, imageTitle: "BIND" }, - 31: { image: img31, imageTitle: "AdGuard Home" }, - 32: { image: img32, imageTitle: "AdNauseam" }, - 33: { image: img33, imageTitle: "Legacy Unix derivatives" }, - 34: { image: img34, imageTitle: "Windows command line" }, -}; diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/01-uBlock-Origin.svg b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/01-uBlock-Origin.svg deleted file mode 100644 index 03e7a9ebb..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/01-uBlock-Origin.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/02-Adblock-Plus.svg b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/02-Adblock-Plus.svg deleted file mode 100644 index 71ab1252f..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/02-Adblock-Plus.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/03-AdGuard.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/03-AdGuard.png deleted file mode 100644 index 61471018cc3319f632d898e32669e1ad3e352168..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 893 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzU_2Dy6XNQVS(v`3Fl}=Mh}?uu zA_O;9Wb7?U+Xz;$u_A3_B~S_^3uXXG2qR+;Pz{ugEQ`#>RDdjt%tlcObm6WdWLZo$ z#0@}kh!lhiC*iUvjNM=dLp%=lOUj1wlnoWB8!A#ZmZgGyn!2eR7&6&gYEyUTrS8s8 z13F_@QSR3Iv_1LhyNmL+HUO;y22SSQ;)3msS$j*f_m!6HXvsfNS#Y4La#v^N?vAGY z6YGz)wH}<(bfT;C^o0InbEjUIJ?HYGMORm@xVd)qtqtpLZ{B=w$Ci6L_uM^l`pLx; z&(B#O(QKD_(>{`1c-Uw?i5^Y8D!fB*jf|3B@= z@gu-UjV=lD3ua(sVrF4sWn*XO;NcaOkdRhXR8rG7a&&QX_X-ROjfjX!Ov%bGC@Lwf zs&43>G8wmbqR8h%d~#}Exs)`PeEE(I_!9I$*YvgXdF19?Xz_qeYA&)pxZPRd!k&YW{9A~Z%$eX{4|UiRBp zwZ9$Tp`D?-`dq;elUw;kBJFD`S6a=wzi|GitZLsi|6~_`m3P```E}h>vxk+sD{to; zZOqu-^<3t)K6j_Lo!Z+_!L-d$k80$;1l$$gR~t34V8?f>BV`GOe>+*)FPv`Gi8!~< z+@s*`+|PL@4*mK3hlSH*wifT^mnC&V}s`A;IDZ-zDF~H#I>gTe~ HDWM4f$?eZ? diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/03-AdGuard.svg b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/03-AdGuard.svg deleted file mode 100644 index b9cb8ebd4..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/03-AdGuard.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/04-DNS66.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/04-DNS66.png deleted file mode 100644 index a32dc2c2f3c759927816550cd39690ee71e80721..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 851 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzU|b&H6XNQVS;#Q0gJF6nh@9CC zB7q19APgWmwVh!~8$*8+LwqPhZ6QNfEyJW11~Ws32~7;){vcV9UND*t*4tdp&{W9~ z;=|Bd$>3ze5a7wsR>?5AmBG~xWM*|f15kmdBSTF-gQFGHaG-2oBS^NPgrO>zAvuB} zDT1M=9waic1!NJB0aOpPD>@Kl6i_h`0Too{GIZ2{oClNwayzOSGU7mNpn9OCKyq>$ zNEYILpiw{(ARFj@AOoZflmhY`D|Mwvt)+V`lZUtX7kLOsJUV;^Q_+3J)8Zu zt!19w%QCx9V8LYexf8Tj&U4z61ko5en-pJVQX=slZP`7uiZBPFOL$S;`T zkKRM(iC5STEPL|z&r|EZ(;wwu*mO`tZ;F*RqL8b#`#FXm-n@T%+!TYT}^si_^)R|cKv=t$uT z4Lh^xs)+yGiTn&2*8_ug1u+a_YJo> zqm<-P9oIT%{_Fn^f0f<-{K>hmt|kqVzY1IB*Ej8+r~Cio%eSAGyZnt<_Wr@@*N z@2*tnN_z2lE}Nmf=H9#PHSX`GZsnc-{nN|Vs$&MGjy;0@J%;nrk4StiP2OW%8x*a7 zA!K^i*Ru?(yuO@Vwtfv`Lz9#9A)d;k7hj)R)vM!mCL&P8dW!K(-LlnJ^9*P2IP&#D gPTw`L_P6u@F?1^>C_b_&i~(f?Pgg&ebxsLQ0Nk8urT_o{ diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/05-Nano-Adblocker.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/05-Nano-Adblocker.png deleted file mode 100644 index cd2b2a06d82f444b7bfd2e2df40b0bd2f93597f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 698 zcmV;r0!96aP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0#8XqK~y+Tm6Y2{ zR8bVhXCe^FATndDA)JelnNgk+AG9QC9-Jtli(TwNDta(_P%AIPHF)_Nrn`p#0?_lq5XX{x#<~6U(A&kDU8+_OC*{{1?unMlT6_!iv1k}=Hc?oywpgoFa&hHiF6FS znt$pv0p&%9(R#s$kt;V)oR^O?o_%=V+#b17)<~@|1mwS4UJdkfJIXM{)f8lIhvsy{ znQTLT##SUJu0rjRl1LD1q*fSQsZd{q<(I<#6F^N6*50iUt~g5W=SQcHAthF!I!$^A}-XlY|c~50?a)j(@Ui0H-}( z1bp>sYoi!y^dmPt10Tad{~Z6KALI|h!cR!v&8K^vn3by|p2!cfK|rxzkzPKC+nKu} zI~?wD)?TGj1tbyIr4eQ1 zK@6t#iM8k?{-K5tOEhXxp%fLB0ttC5UNk9+* z!ypiw&2BKjCX>@@byzGwgCM4+P@4^!n1Dd5*AuO+L_>o^BEe6cLhI__swyx+YHJ-e zHAG8`qpHf)*a%4^m{yDQ_S(C;;M=#MTel#E0#&JA%jIZK528|`N+kwbg`$7?@BCg&T^4I3G;|~^>@kaFrqNzSMD%gFCOUnB$+XewRtDn@oo){ge-IS~hlfux zm~WU&n9hJ03=^9TF`1)WF3e=!;qxEG#5h zaJdkVcPBB?!Q%1V= z$C9zJ4|8%zKHnpVBL#wKLEQ9)4Ucnkeev;6^73A8+2Tt`m`P0ZCMC^m+<333$eWTf zo0Q~9O?|d~`)qQuCoRpJmgY}MA=A_Ssi}d~G%_P2ke=?#%nW8^OlM^UGc$dgvmJSP zGuhex>}($pd3mmafF4bau|(xCzcQ zrdIpqa&RoWQaPs4Al=<2jYfa}KBiXVYIU%?8`WrnJw3QqYaSSI3=9PN`d*KZL*wI~ zkr7y@Lx9%nfk~WtJ!~*Ij7G?0n%3zcv)QNDBW5$O6JoJ=jYeQC%xcB0))|utvDr7(uvP z3ke7Sce_2HxEDZpJOoLqlCf;?84|u1i;5|3;cac_q*7^nd;9rLfE&SJ@a_Nj z2Vnj`B-j7Iqfiz}3b$=7sWQa0Jr{(05iwxRAheUg-iqHgJs2t&Y#D5l$y~w-FI)dt z{rV^4xv{15A<~CiyLT~^_j2h%UBc|}Rf)C2q6>YP*-TDf5xqE|T)L^c>B}+OgQUGO zXUCcH=2B_%8$7PPx$(ov(?1<9J*#rP)XU#)oGTkl=s0A#G&;%r^%J&$=sX)r(~JJR zbi{ilzAP|LeZuzLc`a?I~s1*RDYIHTlsV>N7W;- y>{}m@>T(_0fC7C7#fHK5j}nyT+mV%P<`%DbWxNqQI`j=VAf+&0w5=<*to~nN)ZktK diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/07-AdAway.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/07-AdAway.png deleted file mode 100644 index 0826b747828b5f5c68248b913283ca6b65ba2153..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 658 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzU^ETz332twEZi<40z^AuXosjM zVI(5*_Wj3qpT2At7Ty6w;^Mm$6yARL^!DTDoe~l|B_(&s$?cMt->s;)TSeveij~i= z-+1-(`RiA2-n@SM?(^5}0s=ckgm+3w?UIq%t*pF9LvxR&=3Z^>eR_KPjEwdf8y_$? zKVWHjz{cjFt?eO4rz2io$3w%8hlig`NI030crq#ZR7&cp)YQ{y>1T5D&K4G(D=s-# zT6VF%;bLRsx#pHDJ-t^aOu9OG%C#v|ug{oyW6s=LOP1bRy6pP$6?Zpmytirdy)9cG z?AiNZ&%Rp+4?o<0@bQV0k58R`dhWv0^B107x%TYp_2)Nly}0+_)uSh`pS^hU>dosH zuin1@@b2U1cOSpJ`}8$QwV@Cgj)EmYe!&ca!Xl#LQ>M+HyJXGJU%&tSW1eek3zYor z>EaloaX$6p(W1ivJZ_0sGw&SfoBd~!VwuG0Gc$~gjkmx5&k_6N)?1$~f6}&G5EK;5 zWVFzE8qXvJ@8NvEomm@l1t#|I=NCN7JPJ6AeG+4smvkB>L*J$v(_fRjh>iR3g- z$%KTjj~>4JmZp8%ymVJ^QUk+>6J=kIZP{WsG^*%(f3F*Pp_;+{7R z=oLv#h63?{eU8@o%(uyIbEd+<^GE)Ap4`%lb$ b|AW>2pQ_tNE&p&}Ffe$!`njxgN@xNAk|#v| diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/08-Personal-Blocklist.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/08-Personal-Blocklist.png deleted file mode 100644 index 9b6888a1b5f1716d987fa850f0aea972f8a17b66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1295 zcmV+q1@QWbP)xN#00093P)t-sOlfhN z006rs6TBr8xD*Px6$-v36SoHdx)=(%5(2&@6TKx9xe@`rB@?(21G^OjzaVR!PY~GR{>;&sa>uB@@FX6Vqs2&s9m&W?RD~6U|OQ!zB~M zB@@78t711db(kT_xDizf#71S#j*D4p*EEwD?7u_ot z<185DEEwf1809S(=PeoPEEnl580;(;?l2nfFdFeN8SgP0@-Z6oF&p(U8ul?7`7#^o zIVJ2lC;K!W{WKo@H6H9eD*HJi|2QK3IU~+YJ^wl*@k1{8LoMq}I`T_5-c?5VOE=(E zM*2%P@K8SNRYdJrN$p%r{aQx>Of_UzKbNza3@`HEyfpqPLd-{ZU`-FJ#i+}Nth4hYt`HzJ8 zkcRD-kNA{{{ga6EnUC?Bk?)(5{FjXIoRjLGm+POG_nVUToRa^Wko2LL{hpNdqM7)i znDC{Y`lFivqL}ojpZ}zq`lz4xtE2y^p!2S${;HwyvaA2Bqxi3<_Oh${v#kEKto69D z`nIt6xU%oPx9`5W^1Zn9y|?hcx%#`b`MkFGy|?ney7s=e`n|XFz`OCmy!^el`@XpM zz`Ojvxb(xl^2NaV!o2p!!Sl(*`NzWg$HMr?!}iI<@yyBe%*gf4$n?(1_0Y`r(9HGK z()ZTV^xN3?-P-rv+xOnv_~GC9gf9G>ig^I`|Rra?d<#Q>-z5O z`|j=f@9+EX@B8rY`|p>{QUp^{{R2~15NtL0000@bW%=J009IA z2M7ua4ips`8Xq4ePgz=BUteWqYHM{@C|(vH$=9aY;l$R45e%!98!&KpY3)-~I259U40g zgtSSiM1{i3!otA7z{teFXJBGw1lE2VU}a}VhzY5ns#QyDN)!_N?0Y}+JPZI>Q53~X zd}!*X1^@;i9nbdO%?14OxLj@=z<|NQ(eb#C3_Y>GZ_i5&j`ZNcd$OLmaZb^*AF7QU z(|d2C^Vj)gHC?yHKlxrO8tuI@+OU0{QO>;6=Jk9i@_Fp8Q9@Frq)l`oOs_=oyrsL7 z6S@&I(JJdhcyUR2uzo$!Znw{zY>#%VjX6D4(pBc6nx?Z@??3L0R0BF`tyEtYlY~>o zA1$lS%E(8t=dr$j3jn_}`t+|`U93c7HepC#4*{_8*{SIo+fZ$S)&3#^fd8zW4RTFQ zX|#1$e*oayX*61wirbK9VBPOU;(vYISY@iSh9NmzjgS*s2J{sYy}(=a)tQ|tf$002ovPDHLk FV1i*rzcl~= diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/10-Redirector.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/10-Redirector.png deleted file mode 100644 index 33fa33b018a4ded7f300ce79fd9a938722d52c81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 547 zcmV+;0^I$HP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0k}y-K~y+TrPRqz z!ax`Y@FHF{dMRNkOChWR2NDkiLehkUc<4b>m*~M)@CkSXqZjuV;O2X9Byr>F77ZFM zibC-J)frQvmLmV;OEc5XkC{#fAs&ynLZMJwmgR{n5{a|~U_Fn=)AxG4lU5JtDS=(q z(Lps)SEI`3^IhZmhSD*#yTDEgg~GfJ(hP&a;7ulzSrA3hWmSH^-y0soEy7eXBd46jbgDVvD@ac0yRx@ zCK8D?z7eSRSS+@ys_G1TWH@%-A&!&=jH4eou6vbAWtQFk9XlZ6z;ahPijDdF6SWEI z!LvUzW$3;U#XDad3q%}1Ht_zxwPEM)i;~ah lm#`W47}uk*ykuE^{sKh}Al)HD?Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y9E;VFFSW*B01IkH6K~y+TjgxCklV=!)KlWow-2P0X%a*u> zjqISK+hk)N7dB0_v&=9+NynxO%y>WzZk#;O+0s%#DN==YJy4)fptL}RwiH?@S`bPR zkU+yuP$9SGb zJN$MLD)+C*SW<*0_z4TfJOtX3Wb}(N5ep z{}fp`(|VW)*W=oSc#Md*U{LfajOSu8sbs-%@iSPs>*@OSOP`~PmjSt~8u`46sgxXb z(Z+AY8;BZCJz388~1@nj(k`5=%s|Ox^ znWd1eOXWQOzi_H41Cy6OfnD$(?EH6^VJzMXxwa49#lJB&e;;a_8zP+(Coh}9RrSF* zJ;xFf7h_ zSY19S45N?UWC^#@!U^@aFr8itpEezL4VfX#>JLGpbwFdArYAFv`q4S;gRE;D9oO8j zjrq{y^wQ$p$7>|CaJ-I797l=9 z0hQ?nWSuSu8?Hi7KY*jcb}KC$Q|-f*yftKP65(x1hNpfHTJzpQuP`1OP67nvof>;5 z;hGJg)jo~03LCO7nP48CL*Li}Ip>it?Lj8DwUZXQlqoP5tVY+*>(E`qAS?4eT5_Xd z5yYXRkb#_1HF720FgV<(AyXYF)`QK}V$Z1tB{>9@?SH2xX0i@%yWzMWz3w*6EVAvy%5bTj(wfU-?DZ` f$!kmXrBKv=yHP=5KObGw00000NkvXXu0mjf^|AzZ diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/12-Gas-Mask.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/12-Gas-Mask.png deleted file mode 100644 index 062dcbd76c5fe62ea6c97a78261f27c00ee2109c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 424 zcmV;Z0ayNsP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0X<1XK~xwS1;MdP zlmP$-(D!*+CTWHcsMHPB(h)%s4&D}RLeS78IA{5XSa(Zd%%aL1;IfCn1;2D$0rdIm zqaJX>JD~2jAI<`Jr0u@K32(gthHcn43SeGzeYU1D1JtaD5BgEKXir2$Gy!gk(ie{{ zXo-l3(g*-gm7-FKi0In3stuu#7M%fr9s}lV zdE%K$M3klg0H`}}O+-Z3Gynjcvn3*8#|Qub)GRm<|9o>D007{m2bR4u3jYBg&xqv* S&-8Wx0000 - - - - - Created by potrace 1.15, written by Peter Selinger 2001-2017 - - - - - - - \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/14-Pi-hole.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/14-Pi-hole.png deleted file mode 100644 index 99c6753a2473dd2491096686473afd82224f1cc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 700 zcmV;t0z>_YP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0#QjsK~y+Tjgrkv zR8bhlfA`Lv4ggT2(@Aiu8YI5!j}dwTwW~%1Q`}(uzJzR!E!bIyf20>S6OI)6Cu#p!lxeXo5- z=)mEB6>17q1zLly)9qij`<$r#&OVpbz{L_9M9{3PDAXJ}9cT+K$~Fv=yO{9;lA&+}B@O{V-``Cs{WTm8NoYsem8#J<3|)k2)l ze5Zmd9Pmp1RIVo%Ur9OpdJ8$W7wddl*Vp{;NxZOllfVs#z63k#Dl zDO1*SEoiX|&=x7}ZW$Mng>GHfHod7ZKBlt4tnIQ6kniW;6!J^`i`^ ictLy=XN7IjM(`WfNewVortex diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/15-uBlock.svg b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/15-uBlock.svg deleted file mode 100644 index 6488ebb04..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/15-uBlock.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/16-Internet-Explorer-TPL.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/16-Internet-Explorer-TPL.png deleted file mode 100644 index 2b8189c8d61f672e43068f02c39c82882351d79f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1056 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzVEi566XNQVStzmRy~OT!Aac)p z(TxwG+}&?Mj9p+7q5!5w0wM*I72Ea#s9kLPOPI!Y61(0=?0hY@4I~?hKOx`0u&V6_8h1NNJ8`iLq>G%ZLlto zcSJYb2Ppu#AM6;Adw_xuVSaf5(gk%7I2geJ0@4n&3mjZvV}UMw3K0Q&0Tez!agY>9 z*;|AmAofd;8lX84*8<%J3P5;J07Doo3l)Tg#?Ch&aZvaGRl)>8&VC;&8QBg@4J%55 z{DK*N?tK59=g<6OUnc$iwQ`>eF@ypYq+vQMLe z+p~_DBjo5QF5WqJ&);3fq;Zp9ykpX*)CiSD0kc*3g1Ez`XWfZ3@fU8D-h5=PScqPB zL^}K9RZ+*An)okHU;avSzWMsIm!D1Yco13)Ou9OrE{-7@=VSXXm$@*CI2-3IzjkF? z?rkvI{qxMa>f4#Scilf%=TX!U&$cYAY|VK+e?QYhhmCh_s`l8qtF)l7?$1)4=D#5# z8zPL4Kb-nPY0;BEZu|D^tXJ9L!CcuClzesbYw4yQPye2!E4S=ic&B5@)h{v)6Lvf? zc@|>Mv^7;yrJ9ZLhuYFfrn*U0opLKpm>=Y&IUQaW*6OtI#TtFpNR9(%+f7zxT^D;H zFfEdKCgUG>#tUg)L5t#-e08>KTl(mk!=Kc|J^oIY6g>893hL=C{=7kb_8ZmA7jOAf zj<<9D7k^wmdKI;Vst E06jV;wEzGB diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/16-Internet-Explorer-TPL.svg b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/16-Internet-Explorer-TPL.svg deleted file mode 100644 index 69780795f..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/16-Internet-Explorer-TPL.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/17-Google-Hit-Hider-by-Domain.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/17-Google-Hit-Hider-by-Domain.png deleted file mode 100644 index ca830def3b20dc4ab04f8c43bb30bde507d3f790..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 636 zcmV-?0)zdDP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y9E;VFFSW*B00qsddK~y+T<&#ZIRZ$p)S2QzBksuHn6i$P} znFM7d1SS0dA@D~C4TL5aDVp>%q6l&5Aew|9w-5Wqo7tBjB7&%J3mx2^wa>ft+)Li3 zK?@dVpS{*zd++x>NB=pVO5N|IOABxb&Pk_3+Q&<&*V^;oS6G!!h1?7RE@N)Ihbs`{ z-H;MqNF4-Dd=HQL1I|nL(Ykz~uom!+HobzMA%T^U63`zkO7+)hAA%k;Ux%B7{tRmY z2Xf^Gr)c=3InXDAk666DTm)3{^rK&4T-z?@R+$@4K^biVyWpNr^cHf18rrBeu6uo5 z8fWcIzc-;>Ali;K=2GqAsyC=-|2^qg3TVY)fi&wl+Lt$+(i$5i+UusExhWkfq>RG? z!4W>CZuA*<*w<#9Lft?&iucFiJwThl1nPC}lQcxot#9FBqrAZmoDOS&zXfIxc!D}s zc$&+UA_doASPBp@&=Pq2nbb)GuCm$SpZ*F0ryS%pK570W5?OT3lZ;$hB%~p=bJ?PEVqr&&EnCUGQ1yWHOY%bw}8+$;;{Ny%3gv9@1}9 WS4!g$Nt%-Y0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0scuuK~y+Tjg&t~ zR$&yz4~Fmw72l#DX6WW%;G$??gXo}8i=v_pp^~W()X)%=qT=GHAU4(#IJoELKTvUP z2~sx^70mP#|75@C>%4TkUdaPL-uIsKoaf&6d@r9}7nf%DU=TK(_fYKR{|DkcXoVFx zhf7EMRcM1emtPHvxljY2;TVEJ9Mzr(3-ncKjxoyG z4v#^apg+f>MPF162cba2C)QH<3WqQbcVHR5!2>iOS%c9JcxV~35;mKW!V9>KcoL@B z*ZPn0i04_>XV3#dzlBGs1iCk0JoyWBPnuvCPGP`}>R?aLpnE2*dgkEIz2Z$ee|Up# z@DtE|Ibh&5Zd3^Kp!vOnte)Pntcij|J^b|I8k8UyV%@{2+BJ8fAId>DTw3)sWK9%2 zq+!8}`ee=KKD^}@sdtTx%HRWpW2q;dH3>mNLk`zKtIpmDl~4g4o{MVwy!~&G%m>Xt zqQDtwz(V_IP1<~K|2HT!f|{ZYNl4S^ZC8V04!nUANHP$rNt5Gk$$=mR!;pcviE<-w z{r^!k5X$T&Y(p^7Ub&RZZWc7?n3~zTqx~%}$HMG45Aeys#tXq^00000NkvXXu0mjf D*nAZX diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/19-Samsung-Knox.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/19-Samsung-Knox.png deleted file mode 100644 index bdb2f96a10eb5df7bd0400fb6b05a171225a84b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 476 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 ws1xF8}}l diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/22-Diversion.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/22-Diversion.png deleted file mode 100644 index 511c8c8cd4392e5a57dc3eb6c4eb4e1bf8bf60eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 403 zcmeAS@N?(olHy`uVBq!ia0vp^d_XM1!3HGvvhwHvDaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(eheoCO|{#XwDmL74G){)!Z!1`SUa#}EtuWQNAptSmF`sZ+SbR;_R_n6Nj( zm)EEHX23?(tgLwnyb1>4K}Ni%R5V7<8}~FDot*Ym#(nI{NAr?{O|}OV4XN zE*)}WebFm2M@nBO>PT(*x12(Od;9C{xkDs)roDWTVvti%V9@^Q;e-GG|Hr(RmF=DW z@^yOihoxOy2kZa;D|A|_$Z*$ff!egEY;2Pk#8}MG*S^h@>U2Qh(hiT%Q2A3V&HulC z^_gvBlLM5D$jr%M144@9lBwRc3mh?NDJg!Njy<)qnwxMehO^Tt t;v%D-(gzXQ(_gPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y9E;VFFSW*B00)|OMK~y+TV;BXr0sl8i%Kh6SlKf?b!j#+H zmRqm3xgNdR>T(ps{=8ga>c4H`$=|j}$U~Lm2ER9px<8m?x&L5U$-fneEC0`lJn?@~ z%Gv*mQ-K&rFGx7^e@5W3|BJ$x{oj>c`0q}S<$-@&L_MI|5#ZlWaqidiw3cs5ZT&wh z^!Wd|(Wm~;jXL#z4hTmAam300vq3og6t9a*p=O|NBLG zz=r)l!@&A@vhjgwZfpKe4>;D>+o&THl_x$g$*#Eywa_j$c;kp0sPc%9Ff0Y&+!;kfnWz!tz{-5A-_fz~e$!3MeRF=miYj@lSBr?|Njh( zFXw2jY*w6vqM$}{#{V6O(O+N8(pdqtwBX-Xv3y|iShgc6>PrnU!jRQADop_zipz*AXh_$Z~~B;??AQxHj0Tug+>8Y00RR6Q6|QG T8_oU%00000NkvXXu0mjf*ou!v diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/24-Slimjet.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/24-Slimjet.png deleted file mode 100644 index 00f899268302075546918b1d7d73cc50995882a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1419 zcmV;61$6p}P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y9E;VFFSW*B01pG-vK~y+Tjgx6mQ)d*0FUsaJ+R6{6#Gy1g^+oFCsg&pGG&?j`<7d_I4&THE)5Sk<{jV|aQ%`q1Rh z6xFYb%B+}49y?5A{SU1U$#jZLmwF{~)$07J_TN?dK6DL?!Z!K}mZ6uBH=2eS!iIt* zUhNt({olc}zKrnCl|BFHd#ETG^bQclK3S5^oBUw-jc~dVstfOc!4#H^r z4Xr&R$P{ae7l&PTu~Y0?c67SqQZL=-$8TcuNfx$6aj@ew7rSD3@S_QFujvW$)sIoz zIgAI!5ojL&3a#lmbUiQ7WFCPZmCGb4@2v0cNq1REfqO6m%R-r0buTwG-JfJE9)mu(o9$1yd0v%eU1x#KVxgzU0^9IQ2&#=pFE@Zj z78aB>auvGzt4zhqbW^%nL8Y^niRg?%_}gw*Y}^{^4ANC-YIR(xSb?0F%jt zmNo+#+RR9;Fd<1|M68H(p%K(V1ETXg5z1(GNPd@*B^{tC`;b~Uh!oNZssY5w`f@req! z`tTS8F!8rIdvSNn3zLlbW@&Ml--;Dy1aJ$@!omnPyb}vRm3NN=Gh0X)34I;Y8lE9q zV#c=QTD%u1>?gj?et#S`AvjE>}X|w?GHP*M#@o5`} z@h!R0{Ns{QXP@ltcF;T8Aa|VZC%EcCt$Y=nqesFoHpJZP##fgsu{BkWD~&^M*G{P) zL}>0KEdH^4#ML*~*G~95!C?x8=e^*#q}wxHgVW^}B-RX&cWOo2gQ4*l%++I4LJj5| zE~;_z=B%<8{)aZ)cAZM$A6yVoTI3O1X<1KKVNI-J?Bj^C*4aU#n=U@QO|P5Vv)>Ux Z{0TNbdz!Dp?=S!W002ovPDHLkV1f%4lY0OF diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/25-uMatrix.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/25-uMatrix.png deleted file mode 100644 index 82663fc9ec327af371eb1f62382d9f3545e23c8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 917 zcmV;G18V$Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y9E;VFFSW*B00|rS%K~y+TU6IRA6Hye#XUE2kt_UF^ER_X_ zBsH+ps2dmVNsJnm#JDv61#VfIXiOA08r=Yf@UV|5Q`!!l>EqscwWZT3FfB}5XlL4K zOTxl)XXsFDemOar-h03AJBNDm20eIw$>Rm#>3e1Vog9eO>nE0N+pSjXy#K4$>oiSs z90xU@&r|Uqq1ck&BkBwC;sg-?BBp#f|~j=HU4pYklWv; z@BO?l@msZ$ESVA@o1_s<5$Ynp=v(rkCQ2$vN@*yH<&ljSV}9fhE8(h`Ia0;MVS?Rf z<)#exxiSY;F_o;9l}wpjHgj@&080_oc;tX%Em1Huaugml4wZIZv2&!h^Vv2uIXRn7 zQMMp-F?Q)7bU@Q3I#iBC+6Wn{fSUj|ib7WqTB#J&3oy>{JY`E#&qEYjnal~t={r$) zw5DBThVVUE?uuepCXIVImrN4n9zq@`EURyCml?)Js7jPE>MO&)o@@`}LOSi(hOZ75 z&lmjx)$gxFB6cQYsMxuTj3Nm|Y(qNdGC8d4l-;)hz(dC@TL^{pXv`KxaO*CqR#IHs z#B<-dRW4uJhR4d=+Z86F1%u!ml&{#vxSdW9+BPqg9lDZKOC(PC(U zax)XD4qWTog!3lJJfLhPlZ`|ox4EeXf(@QO+RNaEGi{Zq!4!z5tBep)Ztm=u;joLk zyj)ya(bv{0>l=19*Em$m4Gl2MrCzDjDHNa*H0?~&EW@Buqoe%LkVoqJ4cX@tCMKGz zt8O-8%4x_(`d^?Y%6MibGcw{KO-{;lv(lYubA8>L1uOy@3kC*_J0npfdrppx@z<`o rq=$#asVM;8x_L#}9kQ$JW!Ck7O*ytvM#VPt00000NkvXXu0mjfdvu%G diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/26-Blokada.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/26-Blokada.png deleted file mode 100644 index cfd376114e59b77b695522882b3ad47615c2e0b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 998 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1A9qCK~y+Tm6L5~ zm1P*me~V==Q!BJ4QG_rl25Hon!K8CGJ^uZq2i|^4QchG+$VAN8RrJ_t~Slu&4`e4(GnF=XYP%|N7tbMYum1 zWGOd@Q&E_o%ZXhG!<@thyK{Z@Px)Q<&pX z%vcO_GRACgh)?=LZ2hg03xb&oPh$i#Q(Dt;%%%01be#9;3DM9OW~MVpa_~A>%EGh+ zYZ?uaTeY0r1Etg^BYdHYdQQa{)Nh;Gni6z39YK1!f}C~pSlsNe`DlboBLe;`U`jv> zI}v3}6%~52*vQsepmmcf91^IPLuCxLmy^mIL)O+pRtwxed>u@hnG-QCOZ+#Ca=hG3 zNVg+`jqpP${fEmr-w~p+!Q~cv7|123xrB`xLfXQP{RJ~>>01rr?hHktK@6X*W`KPz z3Bl5P9rjD7iLMauc9pY2IawbSQXma`M*j}0WK655#YeV4Q>UwFqA5UKTPddAkFPPn z=Yko*?6exSBF{a@qCGC}sMTo;vlF#24Pjho>kO(lQ7S9|Av&goz-N&ezOP`Bvg@n}NtY9OFH7xPAdFdgR>~Uz6w=yuj0^6pM!>{P_wO-o1$okUH2Tcw} zlWfxjbG&_g4{)pge{5kAJOh)an{+hKoY%sBu&aoc49uZf&*ygUh`N>Jw7HC0d+c}F zoj>Fx%d5E4OaJ$HJ)dQ&tTO|1=#p-| z)@uoe_SaT&kC*n};)RE~>nlGE9?X1GOrzcNj{jd+9k#9J?d^~AUS8hZgT8UVpMcQH U^2Mz=7ytkO07*qoM6N<$f;}bU1ONa4 diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/27-hostsmgr.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/27-hostsmgr.png deleted file mode 100644 index 349d5b17e0e182d6a05c9e8352a0d5a055ab27a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 750 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0)t6JK~y+Tm6Xd* zT0s=X{ga3Zal^t@7hSmNs%cW(b!VCgiwXo2V=yMQYA9)F2ysD71p1mBO#IZi(BLMoNwcsw2yi^bc8Hz^bfSXp@muXpkfMu_5T#A44eJNpQByM0j9>2wf@ zL{Ki5sf!`DW2Lf9m?biqIZRLA!^FhnL6h_Ib0iW8uq!Z=Xf%p=JdVvx2ZCFeTS8x9X&(q_*jg273Qj*i~lgrQQY(9g)o2rL#0 zO%Doha_iv#A~nkU2lN?Sa2KS8_;DSA@Bv=IPd~V?c;gWe3J3^Cx3TJU!}oa;{&hdz ze-aT+#38Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0@O)FK~y+Tm6S_N z6Hyd~XQosO3m_y$MSSdJL)4%NiMr6ljmD^nF)=3UhUh|fMibPy(h%b#Y)tS0Fh}F?c#W3E8%O0;>5hfL155qYVK# zD=m05Gy&J#Bk&?H1)=z|VqMYcjQ~4r1JDtQLU(w9?w} z9l)k0861%XxFY|AXE^6w<Q7&cM-5AGFNOLk_}&u{Z^sb^iDha2btD$s}}!qYzFk z(@qM$`{+pd9bU+^y5Y{?C?lg|`lV`sc<8bJk7y9t{NCu=6qT^jdpyQn;hO6tksRD{{W|H;7 za+3Z|BP18Q!5aw%%!iCph^Iodt+gN6hMp28rMmU73fPJdM=+#=xMR(Dh=y4?I!i3xi}D z9f>q!{dW3)(7pfiTm_It?n1GD0&IA6B&^$L@L&f-H=56+c}fy)R(_2WXxur@=ha$`3*IY8QeBrjcfn_002ov JPDHLkV1mqObJ_p^ diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/28-personalDNSfilter.svg b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/28-personalDNSfilter.svg deleted file mode 100644 index 90fd8f734..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/28-personalDNSfilter.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - -Layer 1 - - - - - - - - - - - - \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/29-Unbound.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/29-Unbound.png deleted file mode 100644 index e6100dd8aeb3483288be1f3e931ed579eef96102..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 565 zcmV-50?Pe~P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0m?~4K~y+TV?YK9 zN3N^OAH2R<;n20$T8Hn-fyA^<-j`4~bp5&Fq3b)94`0;=D?|qJ`|k_LAG|g}{?N7G z@`tYf2VsrFw_HJT%15tT!Nh?0H_)KTTE`v(_w9LGmDVG69wU<<=bj&mf}X`(H}h2Su~CPThYU-MSx&N>S^8 z^mh;+Su;qzh=$jH24PY2XV^72{@2xO2GiIy3k#dQW{{I}GLn_`KS_#a8Cn0c5)$?% z;J~P_uV>QGNR3xh%X^AXvzmI|b9MF9B%lr^utsE{r`OG`qgUMm@+Y!pkpFe{synQ# zN_nA5aRYPnb_G3y=9NIrzw`~7*BTi$gF_w_FfafBn1nOOUpWR>00000NkvXXu0mjf DC4~J` diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/30-BIND.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/30-BIND.png deleted file mode 100644 index 74723afaf1d359782a9c73db41ef2918958493fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 zcmV+j0{8uiP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0i8)iK~y+T)l)l5 z!%!Igv^Xg^2%>I^;A9s;@F)0K9J=Wsn#aAF9G!~bPjD3%ClNOhQE;lzN0PQ_+DQjN zsJOTZeZ_NcQe%BU)8gQP!@VK-&OP6EZsUKv51?qp5S4g$$Sl6Xpp(YCeM#|#6AU^Ht*x-{H!r(o2S1;q8yGjq5; zZ_s)Q1vPsSZI4E#A(KW(aLAksUr_uhy!42{-otjt_On>O?%QNe6~ZFWSK1a`GUo&r zvjvx4PgGH>I|Zyu{yh{?@8qXxD>Ks*4Rgw${pb0Mbo=4of#@9pdgq0aG(GhI0000< KMNUMnLSTZL9Ne`4 diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/31-AdGuard-Home.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/31-AdGuard-Home.png deleted file mode 100644 index e217b6879cfc0f52fb498073717e3b35fa925daa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 878 zcmV-!1CjiRP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0|QA!K~y+TeUn*l z+E5UM`P+S|RH;uO*-iD>! zZX+BHBbiJ>5CkZSfJWt&aev$&+|C> zaSEH=2D{6FKi8M=gnbBcVbHs5HVc_mlh5a&v6f3^9eS;fDz(<`pw;W)aWa7=z=iPb z*LR#ce&W*Y#7!`OSmF*DL4+vD$SHZqs)l@_1g%s?Nndj#PQN*g z_Z*UZ3Vc?8%qFR*3TsVct(8onEuX<)fbnDui^uPI0XiCuB9&qS8$M!A1TP5?l`JGp zhE^`1%7ke2?M@rLK4UZ*^b`q^1!&!RORwlCREj9q zbyQnSu-jyP^f9cMd zcdf?^MSh@DNRaptCvrD|CozIgLS#y+ioU0oo-Zx%7gDMvYC9e|I{*Lx07*qoM6N<$ Eg2&N_MF0Q* diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/32-AdNauseam.png b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/32-AdNauseam.png deleted file mode 100644 index 773f3c556bcda75b5576d8af06e9211ae2b203fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 713 zcmV;)0yh1LP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0$xc(K~y+TwNy!H z6hRa%y(r>A!3D&lh~Pm4K?J3lu4)|@6f_=OE&&zB1(zf!XdH8h2u3Ad^q}H)3OZd~ zlZ-?U5pxqf3L*%4P!EAjEfWP1+E+b2LyuF3QS`&7KkvPM_3O{?A^$aE63^nk?kWem zD}`Dj^r{OuRefT|=XojQj!IrHhVXgBbR1FLpTaE>`DUr*Iny6Flj~BrHO2$81fq9| zQ3qy;A=S0e*PBwR9>roj8y&rD8g*!9lQT8N+0?R>CImotR*+fGjD$v zG|Zmnrq`g}73He_gcr|snMG9ntmJ2w6R}yZY9kYY?vI%2$zr&{8>gA&0&|RTY7RI_ zrY_^ekv7hgE7~xdRNo_ln$u2_smFNU&0_eGz6qwiEY?h_M=>vX+(n|Zk35)JkLULW zCaAiCVV}?H8VOy9YpU%o(x&|q#;96}E>D$NZQF~1h6An$1=xk@Q8YrH)1b>iUEBW_x60<00R%3t<|2hM+w{FDrZcgQeh?)U( zcn1S63Z{B7>j7zwGwa_Z|C>BBHW@`gL6>3lLxBff|f_brAm+MSBSNS6CJB>K5_~u?2u~(+sCV6rvtRJq~;b zMg`P;&|X3}L+HGlGjp=et3l|Wft$qA>Z1V8r28|B7muLZ{dT8HY}!M80^I!&*8%?k v^Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0{BTpK~y+Tg_Lhd z6JZ?3C-kCszUfUb2evmtiBl_ci1YsxTuYE;V3MST7QN_&P|1jJArVwdBCH@PsThp3 zG|+hylgN4|)3R;(XPa(wyZyP{ZI!$IdbZu1)oy;_1J50NKm6|Qc}|cmeSLj<6bi*q zLqh}8*w`osfShb_HU2a;HFZ{3S3_lGC5(JooTO=bnGcGhOe9I>bJfggZEYP@tJNTt zN@3MzLrgdVVICMJ3~sl#ovUWf@bIu%r_+H_sf1vNMl=%ve&RxRcHuz(71!APMp)KL zfeJWL2$%Sv=rA~U5$0H5m(wg!1}squ6uE{dIs!qAhYY}kp1_jGHo?#?Lb+Tnesi}0 zqH*EWQ3zn6AD7~MHCv(Q!o|dTCys3Iu(r1L$?WVbFzW^gEIkD>5JV&uhBywF7hY*~ ziS;%?1{_WvVRLhHURPJwRxB37+Y9hl41*^?BM&a|5@5jQ7$U#7Xqh`;bp~7km9pMf8o zCLQr0je1|0;Je)m4<0{*j?VLdu+)Y{an?LEn0E@PxwHG&=_*ZpBS($hoF*O72^A98 zw?ogR%kW$~3M=jqtZveOVYYF?*oT^u=yc^T)*!*B;#guMv%XK9DjD$rjg+?$EMrj` znj?ArEhXF{Dx|ET9Lti&jGa0R>`Xnxs3lGZP}Cnn71ut4)fM7pTNooGSh!<4eF;Vk z(HR*)EV+G(R3UWW+#Hyl6j*RM6ALTu(+Qz}Tq2B2l$m}{mO@mIr_&b$J6QNn{1`ISV`@iy0XB4ude`@%$AjKn>ZRE{-7<{&)M&docw{9MxCmcrH|FcPlSD(DLxki5ei{bMY9zxa$k#5&!Sdkq&j)3@9~SL=P+;*w z^={sEn@j@<2LYCjMIASD*mmFjC%a&ymge-+68*iA_ZZmw; z>=Po(-fD|*eW=>ItnhY@Xy4-(^4Au0g)M|3Mfv{+-tj2TZ?H~SdyU^{HZU$2JYD@< J);T3K0RW$*#Bcxr diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/imgs.d.ts b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/imgs.d.ts deleted file mode 100644 index 1090848f7..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/imgs.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare module "*.svg" { - const content: any; - export default content; -} - -declare module "*.png" { - const content: any; - export default content; -} \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/index.ts b/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/index.ts deleted file mode 100644 index d3055c53e..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/imgs/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -import img1 from "./01-uBlock-Origin.svg"; -import img2 from "./02-Adblock-Plus.svg"; -import img3 from "./03-AdGuard.svg"; -import img4 from "./04-DNS66.png"; -import img5 from "./05-Nano-Adblocker.png"; -import img6 from "./06-AdBlock.png"; -import img7 from "./07-AdAway.png"; -import img8 from "./08-Personal-Blocklist.png"; -import img10 from "./10-Redirector.png"; -import img11 from "./11-Hosts-File-Editor.png"; -import img12 from "./12-Gas-Mask.png"; -import img13 from "./13-MinerBlock.svg"; -import img14 from "./14-Pi-hole.svg"; -import img15 from "./15-uBlock.svg"; -import img16 from "./16-Internet-Explorer-TPL.svg"; -import img17 from "./17-Google-Hit-Hider-by-Domain.png"; -import img18 from "./18-FireHOL.png"; -import img19 from "./19-Samsung-Knox.png"; -import img20 from "./20-Little-Snitch.png"; -import img21 from "./21-Privoxy.png"; -import img22 from "./22-Diversion.png"; -import img23 from "./23-dnsmasq.png"; -import img24 from "./24-Slimjet.png"; -import img25 from "./25-uMatrix.png"; -import img26 from "./26-Blokada.png"; -import img27 from "./27-hostsmgr.png"; -import img28 from "./28-personalDNSfilter.svg"; -import img29 from "./29-Unbound.png"; -import img30 from "./30-BIND.png"; -import img31 from "./31-AdGuard-Home.png"; -import img32 from "./32-AdNauseam.png"; -import img33 from "./33-Legacy-Unix-Derivatives.png"; -import img34 from "./34-Windows-command-line.png"; - -export { img1, img2, img3, img4, img5, img6, img7, img8, img10, img11, img12, img13, img14, img15, img16, img17, img18, img19, img20, img21, img22, img23, img24, img25, img26, img27, img28, img29, img30, img31, img32, img33, img34 }; - diff --git a/src/FilterLists.Web/src/modules/home/components/softwareIcon/index.ts b/src/FilterLists.Web/src/modules/home/components/softwareIcon/index.ts deleted file mode 100644 index b3f6cc39f..000000000 --- a/src/FilterLists.Web/src/modules/home/components/softwareIcon/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { SoftwareIcon } from "./SoftwareIcon"; - -export { SoftwareIcon }; diff --git a/src/FilterLists.Web/src/modules/home/index.ts b/src/FilterLists.Web/src/modules/home/index.ts deleted file mode 100644 index bace2e88e..000000000 --- a/src/FilterLists.Web/src/modules/home/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { HomeContainer } from "./HomeContainer"; - -export { HomeContainer as Home }; diff --git a/src/FilterLists.Web/src/modules/home/interfaces/IColumnVisibility.ts b/src/FilterLists.Web/src/modules/home/interfaces/IColumnVisibility.ts deleted file mode 100644 index 3f11fd9a6..000000000 --- a/src/FilterLists.Web/src/modules/home/interfaces/IColumnVisibility.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface IColumnVisibility { - column: string; - visible: boolean; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/interfaces/ILicense.ts b/src/FilterLists.Web/src/modules/home/interfaces/ILicense.ts deleted file mode 100644 index 52b42da81..000000000 --- a/src/FilterLists.Web/src/modules/home/interfaces/ILicense.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface ILicense { - id: number; - descriptionUrl: string; - filterListIds: number[]; - name: string; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/interfaces/IList.ts b/src/FilterLists.Web/src/modules/home/interfaces/IList.ts deleted file mode 100644 index ff8c6cf81..000000000 --- a/src/FilterLists.Web/src/modules/home/interfaces/IList.ts +++ /dev/null @@ -1,22 +0,0 @@ -export interface IList { - id: number; - chatUrl: string; - description: string; - descriptionSourceUrl: string; - donateUrl: string; - emailAddress: string; - forumUrl: string; - homeUrl: string; - issuesUrl: string; - languageIds: number[]; - licenseId: number; - maintainerIds: number[]; - name: string; - policyUrl: string; - publishedDate: string; - submissionUrl: string; - syntaxId: number; - tagIds: number[]; - viewUrl: string; - viewUrlMirrors: string[]; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/interfaces/IMaintainer.ts b/src/FilterLists.Web/src/modules/home/interfaces/IMaintainer.ts deleted file mode 100644 index 421ce83c9..000000000 --- a/src/FilterLists.Web/src/modules/home/interfaces/IMaintainer.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface IMaintainer { - id: number; - emailAddress: string; - filterListIds: number[]; - homeUrl: string; - name: string; - twitterHandle: string; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/interfaces/ISoftware.ts b/src/FilterLists.Web/src/modules/home/interfaces/ISoftware.ts deleted file mode 100644 index 840a05fb0..000000000 --- a/src/FilterLists.Web/src/modules/home/interfaces/ISoftware.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface ISoftware { - id: number; - homeUrl: string; - isAbpSubscribable: boolean; - name: string; - syntaxIds: number[]; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/interfaces/ISyntax.ts b/src/FilterLists.Web/src/modules/home/interfaces/ISyntax.ts deleted file mode 100644 index 2dd8fc9ee..000000000 --- a/src/FilterLists.Web/src/modules/home/interfaces/ISyntax.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface ISyntax { - id: number; - definitionUrl: string; - filterListIds: number[]; - name: string; - softwareIds: number[]; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/interfaces/ITag.ts b/src/FilterLists.Web/src/modules/home/interfaces/ITag.ts deleted file mode 100644 index 62e526469..000000000 --- a/src/FilterLists.Web/src/modules/home/interfaces/ITag.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface ITag { - id: number; - description: string; - filterListIds: number[]; - name: string; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/home/interfaces/Language.ts b/src/FilterLists.Web/src/modules/home/interfaces/Language.ts deleted file mode 100644 index 4726a4c01..000000000 --- a/src/FilterLists.Web/src/modules/home/interfaces/Language.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface Language { - id: number; - filterListIds: number[]; - iso6391: string; - name: string; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/modules/index.ts b/src/FilterLists.Web/src/modules/index.ts deleted file mode 100644 index 26437089f..000000000 --- a/src/FilterLists.Web/src/modules/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { Home } from "./home"; - -export { Home }; diff --git a/src/FilterLists.Web/src/react-app-env.d.ts b/src/FilterLists.Web/src/react-app-env.d.ts index 6431bc5fc..6889c6b37 100644 --- a/src/FilterLists.Web/src/react-app-env.d.ts +++ b/src/FilterLists.Web/src/react-app-env.d.ts @@ -1 +1 @@ -/// +/// \ No newline at end of file diff --git a/src/FilterLists.Web/src/utils/GetContrast.ts b/src/FilterLists.Web/src/utils/GetContrast.ts deleted file mode 100644 index 0dc5f4e55..000000000 --- a/src/FilterLists.Web/src/utils/GetContrast.ts +++ /dev/null @@ -1,8 +0,0 @@ -//https://stackoverflow.com/a/11868398/2343739 -export const getContrast = (hexcolor: string) => { - const r = parseInt(hexcolor.substr(0, 2), 16); - const g = parseInt(hexcolor.substr(2, 2), 16); - const b = parseInt(hexcolor.substr(4, 2), 16); - const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; - return (yiq >= 128) ? "black" : "white"; -}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/utils/index.ts b/src/FilterLists.Web/src/utils/index.ts index 4646f2030..d22b49973 100644 --- a/src/FilterLists.Web/src/utils/index.ts +++ b/src/FilterLists.Web/src/utils/index.ts @@ -1,3 +1,3 @@ -import { getContrast } from "./GetContrast"; +import { nameof } from './nameof'; -export { getContrast }; +export { nameof }; \ No newline at end of file diff --git a/src/FilterLists.Web/src/utils/loader.css b/src/FilterLists.Web/src/utils/loader.css deleted file mode 100644 index bdf0e7446..000000000 --- a/src/FilterLists.Web/src/utils/loader.css +++ /dev/null @@ -1,70 +0,0 @@ -/*https://projects.lukehaas.me/css-loaders/#load1*/ - -.loader, -.loader:before, -.loader:after { - -ms-animation: load1 1s infinite ease-in-out; - -webkit-animation: load1 1s infinite ease-in-out; - animation: load1 1s infinite ease-in-out; - background: #000000; - height: 4em; - width: 1em; -} - -.loader { - -ms-transform: translateZ(0); - -webkit-animation-delay: -0.16s; - -webkit-transform: translateZ(0); - animation-delay: -0.16s; - color: #000000; - font-size: 11px; - margin: 88px auto; - position: relative; - text-indent: -9999em; - transform: translateZ(0); -} - -.loader:before, -.loader:after { - content: ""; - position: absolute; - top: 0; -} - -.loader:before { - -webkit-animation-delay: -0.32s; - animation-delay: -0.32s; - left: -1.5em; -} - -.loader:after { - left: 1.5em; -} - -@-webkit-keyframes load1 { - 0%, - 80%, - 100% { - box-shadow: 0 0; - height: 4em; - } - - 40% { - box-shadow: 0 -2em; - height: 5em; - } -} - -@keyframes load1 { - 0%, - 80%, - 100% { - box-shadow: 0 0; - height: 4em; - } - - 40% { - box-shadow: 0 -2em; - height: 5em; - } -} diff --git a/src/FilterLists.Web.V2/src/utils/nameof.ts b/src/FilterLists.Web/src/utils/nameof.ts similarity index 100% rename from src/FilterLists.Web.V2/src/utils/nameof.ts rename to src/FilterLists.Web/src/utils/nameof.ts diff --git a/src/FilterLists.Web/tsconfig.json b/src/FilterLists.Web/tsconfig.json index 0980b23fa..213390d38 100644 --- a/src/FilterLists.Web/tsconfig.json +++ b/src/FilterLists.Web/tsconfig.json @@ -17,9 +17,10 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "preserve" + "jsx": "preserve", + "noImplicitAny": true }, "include": [ "src" ] -} +} \ No newline at end of file From c49983df57507995d945dbbb9c47a90a7f272526 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 15:04:26 -0500 Subject: [PATCH 162/163] revert removing Dockerfile --- src/FilterLists.Web/Dockerfile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/FilterLists.Web/Dockerfile diff --git a/src/FilterLists.Web/Dockerfile b/src/FilterLists.Web/Dockerfile new file mode 100644 index 000000000..a6dd8bcb4 --- /dev/null +++ b/src/FilterLists.Web/Dockerfile @@ -0,0 +1,21 @@ +# Context: . +# Command: docker build -f src/FilterLists.Web/Dockerfile . + +# init base +FROM nginx:alpine as base + +# init build +FROM node:alpine as build + +# install +WORKDIR /usr/src/app/ +COPY src/FilterLists.Web/package*.json ./ +RUN npm install --only=prod + +# build +COPY src/FilterLists.Web/. ./ +RUN INLINE_RUNTIME_CHUNK=false npm run build + +# final +FROM base as final +COPY --from=build /usr/src/app/build /usr/share/nginx/html \ No newline at end of file From 6f318bcf7dc7a4865c9432acc586325537b879b7 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Mon, 2 Sep 2019 15:15:34 -0500 Subject: [PATCH 163/163] merge new Software icons from master --- .../src/components/softwareCloud/SoftwareIcon.tsx | 12 +++++++++--- .../softwareCloud/imgs/35-Shadowsocks.png | Bin 0 -> 583 bytes .../softwareCloud/imgs/36-ShadowsocksR.png | Bin 0 -> 693 bytes .../softwareCloud/imgs/37-Shadowrocket.png | Bin 0 -> 633 bytes .../src/components/softwareCloud/imgs/index.ts | 8 +++++++- 5 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/FilterLists.Web/src/components/softwareCloud/imgs/35-Shadowsocks.png create mode 100644 src/FilterLists.Web/src/components/softwareCloud/imgs/36-ShadowsocksR.png create mode 100644 src/FilterLists.Web/src/components/softwareCloud/imgs/37-Shadowrocket.png diff --git a/src/FilterLists.Web/src/components/softwareCloud/SoftwareIcon.tsx b/src/FilterLists.Web/src/components/softwareCloud/SoftwareIcon.tsx index b1618bf98..d8a397863 100644 --- a/src/FilterLists.Web/src/components/softwareCloud/SoftwareIcon.tsx +++ b/src/FilterLists.Web/src/components/softwareCloud/SoftwareIcon.tsx @@ -33,7 +33,10 @@ import { img31, img32, img33, - img34 + img34, + img35, + img36, + img37 } from './imgs'; interface Props { @@ -87,5 +90,8 @@ const icons: { [id: number]: Icon; } = { 31: { image: img31, imageTitle: "AdGuard Home" }, 32: { image: img32, imageTitle: "AdNauseam" }, 33: { image: img33, imageTitle: "Legacy Unix derivatives" }, - 34: { image: img34, imageTitle: "Windows command line" } -}; + 34: { image: img34, imageTitle: "Windows command line" }, + 35: { image: img35, imageTitle: "Shadowsocks" }, + 36: { image: img36, imageTitle: "ShadowsocksR" }, + 37: { image: img37, imageTitle: "Shadowrocket" } +}; \ No newline at end of file diff --git a/src/FilterLists.Web/src/components/softwareCloud/imgs/35-Shadowsocks.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/35-Shadowsocks.png new file mode 100644 index 0000000000000000000000000000000000000000..62cc490d44fbbd4c07635680fe1206addc5d3c80 GIT binary patch literal 583 zcmV-N0=WH&P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0o+MMK~y+Tt&=}U z96=PuHw04zErS1U=Jcu{K~zK$AzGwR(pcDtMbe0c5VRD;ow)%UD-o=;3M3*%QG!GS zg?+nsrV&XRZBnHYs}L(SiJsr;)7y1VJ-vMJVE3E%e(%l9uJu19N2!q?3sYP>tx~&d zLOI0N!xYnQi_o+RSjG>b-7#LepM>$6grXHdPA_2$?BtaEBn>r6MW3an5a>LV`?uUs zF{j?HxJflg?JWUz1;RAHg>nzGK-%K;n^k3~4uy+B5W~L1TMl`OCb%rBm`T;*us>lN zC&40)4^lhtuKNIXb9q+6&;hWF~&daR1M5oEdC26 zasad^bgB)oYFx;EBuCLMqX0`%AG#k$lCqIbjCw+t?WX{L%dze^oMzmGD$Uo5nC%Rp z)4G5Cf#j*?ne8GglX-+2T?qK05J~S1qoR@{8>PZ_`eoAVWy_MvF}XmOAxt{KsduY% zc(VjYGLPvGa={QkIrV<3H9Jr6r*z;*CUIsz0>F=)lAo%STaVA=Jtpk3dKMnD?SJ&o zMUsYuc3!iUpM*{A{v_D;7q$vh+@@E6{i-&blC8po?RLf#z2(=!l^9PyPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0!m3lK~y+Tt&>Y= z)KCu3XXDtJ zQM5%-@kPblWTtMUC_>%3kWvIe>Z-nvC+TUE7@Zj(KO8vsJic=uiS|Fm`;<=ZzbR?i zo4MsYWWrVy`a2~or-NDQKEl8=W;y+o`ZF=<8ce9W2>Ct-BVZ?$)F&>L&V{XxHg35$5jGFP-Aps#%mhI7jLLtnCaKn8<471puooD+6^RLTmfGS< z$Z{)Q_6RBI7(4X4LI*zg&L9Ob6F1$X!{lE)KZ?@GdW zmt9_i!4f9FMheLgG{vm)R)jU(sD6mRPpUapWUy9)8zsP$7 z2MIT;)$(a$!n6cTl>z@VK1`p$^c}7YqeJe_b$M;!g8^vX)x1l@;Vh1Zw*ta(#bx bt!Y01v5}{Q%d9Fr00000NkvXXu0mjfw`MoO literal 0 HcmV?d00001 diff --git a/src/FilterLists.Web/src/components/softwareCloud/imgs/37-Shadowrocket.png b/src/FilterLists.Web/src/components/softwareCloud/imgs/37-Shadowrocket.png new file mode 100644 index 0000000000000000000000000000000000000000..816f0fd51777a4ce6ea2b73b4b32c2de84d82299 GIT binary patch literal 633 zcmV-<0*3vGP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0uD(;K~y+Tg^$Z? z6Hye#$Jb85jVu2G-HC486!wOljgpzRlxY=AEK;XY zQ%wT_ZEI1}Mg_6f$ENgVGMSrsWdf5P=W!*iH1P)m=X~e;xZhA4aX4MN*gS?J2f3S&7D(eIOp2F_Od@b-VV^+=H zUU`>ewvwCs?+UZBY!$CVsZ@ntq=>q?{5{DORMn9(muV@A#x*si;7-dxz73!&-hS~^`lc(dsGZ)r(ly5$uP5UDZkPozVmIUTrp z9ZtmYej?YWYfwCxo-e~xRtL|Zw2#P*dBBL-`;7RJtp6uUqa*kH%LmB128#LvDT>9D T7~`tB00000NkvXXu0mjfG(sO` literal 0 HcmV?d00001 diff --git a/src/FilterLists.Web/src/components/softwareCloud/imgs/index.ts b/src/FilterLists.Web/src/components/softwareCloud/imgs/index.ts index ecb632bbf..6d65459c3 100644 --- a/src/FilterLists.Web/src/components/softwareCloud/imgs/index.ts +++ b/src/FilterLists.Web/src/components/softwareCloud/imgs/index.ts @@ -31,6 +31,9 @@ import img31 from './31-AdGuard-Home.png'; import img32 from './32-AdNauseam.png'; import img33 from './33-Legacy-Unix-Derivatives.png'; import img34 from './34-Windows-command-line.png'; +import img35 from './35-Shadowsocks.png'; +import img36 from './36-ShadowsocksR.png'; +import img37 from './37-Shadowrocket.png'; export { img01, @@ -65,5 +68,8 @@ export { img31, img32, img33, - img34 + img34, + img35, + img36, + img37 }; \ No newline at end of file