From 9a864c4df521d7d010884cb3e018888a1e81c44d Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Tue, 6 Mar 2018 11:55:38 -0500 Subject: [PATCH 01/31] feat: Add component for reloading saved pins Created separate component for preloading saved pins with additional functions that can be used independently for future features (such as viewing pins from another user) Issue: #183 --- .../icons/leaflet/marker-icon-fav-2x.png | Bin 0 -> 2481 bytes .../assets/icons/leaflet/marker-icon-fav.png | Bin 0 -> 881 bytes .../components/LeafletOsmMap/SavedPlaces.js | 128 ++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 client/src/assets/icons/leaflet/marker-icon-fav-2x.png create mode 100644 client/src/assets/icons/leaflet/marker-icon-fav.png create mode 100644 client/src/components/LeafletOsmMap/SavedPlaces.js diff --git a/client/src/assets/icons/leaflet/marker-icon-fav-2x.png b/client/src/assets/icons/leaflet/marker-icon-fav-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd17a2aa2a4eec0049c21c1299630614571d332 GIT binary patch literal 2481 zcmX|DX*3(?8V(7GEkq4!nMT^NOc6<}DJu4q(4r_)Ld0?rL`bSslBVdixt3O264v%n7qLMw6+`LFhktB-{#7S#uO9oa15KX29!5Ps} zlz1$|3h@^%R+N9gMk3&UjnE>k5V-Gza9_e{xLpjD3^y?}H6Wod=5R9$LzIbyIoens zjy6J>B8@DNC}RU76xPTBYlMRTeGt~ta7$`PDAvQ?@ozFwWrYZ*(PFVkB%Mw-q+<+Y zs9{Kyg@pyu2#rLe4MY?>359X8=RS}OIFkVJaPfcx1#V=VkeKxx=yivHr`!8?#$p-JMC{8@g zv`p3*PzCCPtO1jNK0uk+A*Nc%hy)L~59EpO%kIJ$67vaqpXl_-JB*XDs9Q`FUx)R9 zFJLVy?WrAI7FW*wjSd7e0|EW!Ib1vV))#k4Z$KchY_3}NjnO?6Rc#Yi3pBqmN|a*B zqM@^wINlsNh$rR^KIg&n#N*F^Wqn0S4?x1zGc(6(v)6ovzz1z`7HOKA+zXhqQSEuj)TNnebpBn#}3lC z0J;%p5(~Lg5E>3LQa7hXdiIXuPyNP8yNigmA-?H8S^F!RFw^9c?^ot^%vWm$bq zz*l2V8G*;z8y=8dC;M|CUESI+N=^>8At zYIj?cFZBwyeg#v3*+bs%EG2-ZxY&0$tZpSpH}7w?%$%&gdL`!m&^jyg2olhy7-Y^jUWb+XcydX*k!=U&FC{aL_i00-&W z=BM{m%guUogcea%e#4AbuYJ(RV>_HF_zIa7AS3+XIJ}l5(H0yP_F%-Ag=GT7X0C;F zT7N3Psm{EYKb?wm`qQ||!3TCPz9x^loih6Nv*01qbkgU2HQ&;>E%w>uek) zsHb#%?x0a`q_Oat3x86!y1pMrSH@;L)lE(wFYZ%_2f{+Jq1g1awWvDS`2zd6yeAtH zE+_hJbQb5vgS`Q*0xck4hChK?@MPxk8|Ri?*FHP@>8Jka%iL~%q`uXX-Gq1=0|c`s zG#8Ty@THpZYuO(+fCE{=h(bd0QJ$E!n1-Iq4v+#8fDwDMH2+-_>iKKaKj1QYo+ny# zgpWs57>eE2z&HdJr0|uU)J?~NqjYi$(&|_lJc$}=H_cl6vp?U#*ybZp-n;h0Q`-gI zB21f1O+{84Z1ZtRwRu%J)s7qA@XZnata841L>V725W1E-z37{*5UJ;1g}tSj?&HEg zBXEsC4W~1YoOlCba6+iW<*6&?Y8e#lQ@(ccL0SocdEhsn+&whc%Yrx!a-Aj$ihtt! z&e*d59qD41B%7!o$_=|pnQ@j9I;6bRBFQb>`1}pJZdQ}vIk%DaV_WYF z0L)uwvgH>}-eJpwbJ{Vt(Cdv5XN^ees~&B`b1C)$|ng6_eOsI zI`A_N0yMeUduc*4aUJ62F#HIex&!)ArP+Ii!dgccjEEnX2$ix7rNNrf!Ih_oP0ir0 zb!e;d@PY3}3C{EO=pW@Q?HMbcRxB*^kk*BhQk**b-BMm!I{dY5SK;b|Ry5z^9wnCRZ2vFk3aKS3wbl?Kgdq{_p>u-^QMoF$jf5&uCv1b>k^KBvV$Y6Mv=!M%jtf$D;G1FK5(#*C#{6b-jYZ#EC zQL7H+iCt2pAI;kQ{q@)I`;8gCF0kWE|xe=g!*0S1-F}K-bRhl?hI5b;A8{q)LxXEwW#?<|e_1&z(MzTd}1NU<+58`%u;l(_(x>>qUR!slnluxqJA j9)=2Nme})XIK6ws0-X4`+ca$R`%eq+;AUTAOJx5K*k@|` literal 0 HcmV?d00001 diff --git a/client/src/assets/icons/leaflet/marker-icon-fav.png b/client/src/assets/icons/leaflet/marker-icon-fav.png new file mode 100644 index 0000000000000000000000000000000000000000..857c156c385b7f371d7f1d7ee1c9973e2ac449f2 GIT binary patch literal 881 zcmeAS@N?(olHy`uVBq!ia0vp^d_XM1!3HGvvhwIKFfe*&hD4M^`1)8S=jZArrsOB3 z>Q&?x0Oc7NZ0suv5|gu2OB9k)(=+pImEP~(ucVNfVyhHx>TBRz;GCL~=}}db8eHWU zl3bOYY?-2DZ^va*VFffGH?<^Dp&~aYuh^=>Rtapb6_5=Q)>l#hD=EpgRdNJbs1V^B zpx~Tel&WB=XQrEMXl$WiZmDNzYH49)qN8ABU}&aqV5x6tqHADiWngJ#V5k5EN_Jcd zHbp6ERzWUqP|JWkTcwPWk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO_g)3fw+}9`7?7_ z`R}iq!yw0a(B4Uq$KvOsnrDRtFVZU216ZwM)-Z2AuxJ182F8Td`^_6{H9NV5WQ9C( zJihFcImPESMdjX)`t{j6z9)GdGnD)h6De^{kLkpW34sg|K-Q@pQlDixtJF@HCUjrF z!8?cbSL2#u?E}UMY(HMy=?~HPEpzHaB!4QuQ)IdZca4?vP3P-M_peXsDO%(7{nCkl z-;KNs*FA|T@2Qr4(sjD|z}|?pau4)A9NGE!K<0zeHUCzYXgq6peSl9qj!`*}Wrd}9 z>pq6!#+e)6-}=O2aBJI}`Ty=-J0^ZV*3MuS+mEle)iUp8{JC?B`GU=EX$H-PR~6Tz z_9g~@ZTmQX=BmE(wOgAQgj_pA_xCM{oT}mWFKk2DiCX4kLa$sUR*M$Bu4k3~p1E#` ztoFLC8#E)dpExP-Yq)Wr*gZ|=%Lk#e%pC@g@2D*i&T=eX&fdsYpn38GyP%(%g;RUb Q5>QU@boFyt=akR{0Q&<`djJ3c literal 0 HcmV?d00001 diff --git a/client/src/components/LeafletOsmMap/SavedPlaces.js b/client/src/components/LeafletOsmMap/SavedPlaces.js new file mode 100644 index 0000000..bca7e3c --- /dev/null +++ b/client/src/components/LeafletOsmMap/SavedPlaces.js @@ -0,0 +1,128 @@ +import {h, Component} from "preact"; +import {makeRequest} from "../../js/server-requests-utils"; + +/** + * Leaflet related imports: leaflet, pouchdb module, and routing machine module + */ +import '../../../node_modules/leaflet/dist/leaflet.css'; +import '../../../node_modules/leaflet-routing-machine/dist/leaflet-routing-machine.css'; +import L from '../../js/leaflet-tileLayer-pouchdb-cached'; +import Routing from '../../../node_modules/leaflet-routing-machine/src/index.js'; + +/* Set all settings for saved place icon +Full list of options: http://leafletjs.com/reference-1.3.0.html#icon + */ +const FAV_MARKER_ICON = L.icon({ + iconUrl: '../../icons/marker-icon-fav.png', + shadowUrl: '../../icons/marker-shadow.png', + className: 'favorites', +}); + +const CURRENT_USER = makeRequest('GET', 'user'); + + + +export default class SavedPlaces extends Component { + constructor(props) { + super(props) + const {user, map} = props; + + fetchAndDropUserPins(user, map); + } + + render() { + //This shouldn't render much (if anything) + return ( null ); + } + +} + + +/** + * Exported Functions + */ + +//Get and drop pins from any user on any map +const fetchAndDropUserPins = (userPromised=CURRENT_USER, mapObj=undefined) => { + + userPromised + .then(res => res.data._id) //get user ID + .then(user_id => getSavedPins(user_id)) + .then(savedPins => { + + let pinMarkers = makePinMarkers(savedPins); + if (mapObj != null) dropPin(pinMarkers, mapObj); + + }) + .catch(err => { + //User not signed in, no saved places to load + console.log(`Error. abort load saved places: ${err}`); + }); + +} + +const getSavedPins = (user_id='') => { + //GET 'search/savedpins/:user_id' + let pinsPromised = makeRequest('GET', 'savedPins', '', user_id); + + return pinsPromised + .then(res => res.data.savedPins) + .catch(err => { + // console.log(`Couldn't get the user pins: ${err}`); + + //rethrow error + throw(err); + }); + +} + +//This function generates markers and drops them on a map (if specified) +const makePinMarkers = (pinArray = []) => { + + let pinMarkers = []; + + + for (let pin of pinArray) { + //create marker for the pin and bind it ot the map + let thisMarker = L.marker([pin.lat, pin.lng], { + icon: FAV_MARKER_ICON, + draggable: false, + autopan: true, + riseOnHover: true, + title: pin.place_id + }); + + pinMarkers.push(thisMarker); + } + + // console.log('User Pins added: ',pinMarkers) + return pinMarkers; + +} + +//This funciton drops pins on a map replacing pins if they already exist +const dropPin = (pinMarkers=[], mapObj=undefined) => { + + //if no map is defined, or there are no pins return + if ((mapObj == null) || (pinMarkers.length == 0)) return; + + /*TO DO?: + Do not allow duplication of pins, + Remove those that exist already on the old map + Hint: use sets + */ + + + for (let marker of pinMarkers){ + marker.addTo(mapObj); + + /* TO DO + Bind a custom container for each pin on click */ + marker.bindPopup(marker.title); + } +} + + +//Export Statements +export {fetchAndDropUserPins, getSavedPins, makePinMarkers, dropPin}; + From 24456aa23e4d95e1917ca1f36dbee7edd82ada47 Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Tue, 6 Mar 2018 13:00:25 -0500 Subject: [PATCH 02/31] fix: Change icon size and change color to red Issue: #183 --- .../icons/leaflet/marker-icon-fav-2x.png | Bin 2481 -> 2516 bytes .../assets/icons/leaflet/marker-icon-fav.png | Bin 881 -> 895 bytes .../components/LeafletOsmMap/SavedPlaces.js | 15 +++++++-------- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/client/src/assets/icons/leaflet/marker-icon-fav-2x.png b/client/src/assets/icons/leaflet/marker-icon-fav-2x.png index 6dd17a2aa2a4eec0049c21c1299630614571d332..9e19d7d2cc374eea48e71cee3dd145c3a65042c1 100644 GIT binary patch delta 2161 zcmV-%2#)u$6Vwy1djWq$NklsDQLx#!q&8*OZicVC0(l0P>Q0aKd`iE zwadz~bhCkVfj#}>%-el?_x_l<_def#lau%E%$YND=FX2ZXU=~u$f8B$j1j=~z^8#3 zz*Jxoa4Ar2cshYIz`udx!0W)Pz+s@rskW_KW3zoHVbK@?d3T{MCj&2Fxr; z?*jG!+kj?Vl?_2w1;+tPfNug5vNi_onA;7t0Y3)T1E`5F!&& z%88>1M)nCrzGr{x9L$%fpgV2>-U3#VJQVXl74VR$^GmLUT@>_zC(t=E#kHawFa_8R ztO17G7V=4c%K&469SmF$DuDuUKQIfp4U4(yfsjCxK@Nh#_{CWMB{x7nHQqkh57K?MskzrOVOL%Zrz4PW5|5u^CJT^lGXMk0xk$ldv>?q(Hs0ny!hBmYVQwmMnyI|ld zx|nRr9RxlBti@e9Oqq2?MoWfvj74<;`cD%cB1kNI7PG~@ zNP{~73cYi0F95B$pU6)DpG5sDHfRFong724=Ev}sq8d1gZYwTm11|GWQzwnP;U4Uj zs|DtkJkK?0Ht0m%BCePK)Ov_~F2y8%8IfiO{^e#ND?WQB&9?k+Or5UnywL;dQuNMR z2i||_gfA@hCa)ZI7E$LROmnpP&LA{9@UKJ|7Lq>9vSLFa>riz9q@ig z`gmX(aHaX3hK`Q7!}22FI@JFCyP>}sdN08HK5zh-r^xPZFeZ4n$gP3V63 zpo0t>JkH=vK3I1WM*1M_z(*YloefF*E^r=o(B^?hB4oK5@uz)+Hry1vBqDt!YC}Hi z*oYuj#K;)sDC=DhIObR=&gyv#d)qV&4a9eltHpK9L*$5~bx@O#zZ#KeQdk`uP1%1q zo?1tlM?Cb>(FHc{`*$5>0=#3v^I1okfAkSKgkC(_-W1&gj0C!4cx(;nQY86cM`F%+ zmgoWwc>+BG`yFs(W(EzYAl^*No|5!vV1 zLq9}hOi21wf#)7X)*~_%k^2o@fk>mtE9I>Vkv9gBwT^Au=k5G;yDHd^pE>jpsAK0@ z^ir}EMWdk?*n*xe?na%#MYN$Ff$6~W^gD(x3&<(}n{juD_32W$IQ!P(|B-*de{lDW zJ`LQ3&TW7X17Al^7;jq2s0F?ZYy|#SlKv#{ZO8Vs0~5Vn&D}82b>9uVfV%Hp@GbPZ z?JnQ~djGIGw!~n(WvB=rRc>)Odn{h?cJ1uj!h*L;n^K-`79+fbFgb^l(qtoRamw6rn0Z{p$#zaPgMe!88x}EBW0KcA@j@AN2cCtAWeW#U-y`qT|4o z-rijUuIj>K)p~(OLwTSI_>`e?qA{o(M8~RaMx-r;xm77Tg~)SZT1S6HS)3)EqqS0a z();c1F!L`q+VCkvI)=d8Nun-9HbiM27wObVe)F)L*y!!s6B)DSi%4AIMqn8*I`3BH zgmWZZk|qVjo;E|Z(!(%{o*uS;@5wj?eR^ZxAn0OqH|{RGa^oEE{Uj!vkmi$!Y#0J> zD@Yp_BAA5Kyd0YtZ!}Q9+wISVSW_7hT-^<-mV& z*uH!uDvWFp&Z3thPo-#7o_K`t3!qRW?SnyV0`5g`Z!3YfO&hG?+l=E9oJVhewz(9_ z5zBFNZ>IY4r3sP46HxDL@G4gxO{?cL5B zFOo9EGVZg2Bzgd$J41O}>PGlZWPY-OsprHAMAm%(bMHr{uJHT>6wY6JLvlAnqZ)Nk z1zqlW;Uwzbj|}?rkGvWyz;z!Cq7&UVev(B<3|3$t(HM#>L$pZGA#$_~L-QyaDjm<4 zs9<(nL@!7(4TXOI1hsoFW)+mj8w8P85ZRLB+uMRjixqDI((Z#{Xg~wys*@NK&`Gvf zn*qpUh!)X`E(%%ku#uGu3O#k#UQuD%bVCA7CpQO`I#rp&-D0^nXfcgAQp^CU=xe!S`?rkbMx1yvQBp zQV`U93&wYc;T6hf>XlVNK_f8YTnrZskG1E^73EYA^wZWQge%Z%@?I-v1In!+z%ytV nRL0Hv*g-+c7-G++DVeB#&&-z!ULwvp?awV-SJW2B(Rb6SJ4Nmfeoh2kGW=cAs7H#(LOTWwIC0e z4*Uja04}%9WZMTP0Z%h{Ko|*B0c(Jpflp!4H*NZ0Ey7`hMFsS;tnxvGLkP9$1e0+! za0r;4W@rR38#r`pQ_Iy!N~MH`nj&yOVA{w(u!=HG;J1HEn_8w+Bv>K+GT>LhbxEx= zN-zi5zqF}kOx(?q2*k)H5pJ$bqcut`Mc&_2onO4K?H<#4QHQg@ z^cPml>xRM8M7_YI97FbDf%gh*6X?m1zeixZv2iFzJthg%hipSnri8F6$Aq*8VJSkJ zhsmuC;Z}s*Ic%(2(s;a7{sikJ`-I*g@MVEs3*CR^M$+_p1-@czXQ|UPfjWQy0pN>d z!#?b%lpBDbo8NyyN7gi~MOP7@bFP_k`hC^n?Z>KsHr!X_t-w4qzG8!Yz-P_xUt(YB z8sIoOt+?PcaAgT~b+UvTR$@gL&ERsg)mAp^h*z}qqDQ-GPkwdU_k^zBGmEPozYfcn3$8~MADw<5Z4 z0|$ZI9qM{bAnvZ&i;?U11J97%X`W4dBbslOZx+E1jh#={o!<5{55i2i{BMN zh{?uwIl*YzX{as%mmD)iU!8rx7DpR4*kWuam7RvMfry+1u5!q9J|^v3z(q7b>jMu~ zu;sc!=_sKyz6-9XkiHT4wxg{$tfz8AjdQg1Mj*ng=%UjWNnX!p^p)T0SdkEGDO-Q6 zI+h)WS4+TA$4qH4(uaT_JK6+zgk*AH@7{$t8i;N>y1*uU|AwPYfd5+Pe8|z}%Yg_- z(2YmiouVbcSl~i}j%!OpdJJ|fW{qcwZs14>-9>%QA!7~clkN2m_Cloj#J7Xfoc-L( zYv%Wc9=^-U01;Lv+`C+anHfC)StfsPmNMg{83qEsPowjgEfzAcc#UE<@%wk(!1s)F z$J`I7Jb*1TW!mB*%Bg>ic2?26pxcR7KLSGJpF79v8S);BJBTGM&=`D+PaM2|Q+W z5x6p9t4d(ExCg}c4!jo9|5*2f_ZD@x;-!^ZTc; zl88_yyCT=NQZFLUi%4z8{N;aAYi!kL%)hIgZFGO|H4zRvcIZ$RoBZoVsL7Cjyl5cm zgt3*S4hN5|TQI0w1bspj+fi>N3$8#nUsj_X{YiAeT4@Rj&@*kz(b$Yjyd@6XhZN8^ zbYrU--Dk_QjWz+e%Sboczy8TU9JL0G1f%h3H5{)M} zEEw{*f<76_5ZH|_UVR*}8xEWSeiC;hkodjV^Jt*8h*(PzX!_d&H^sSsv9D-|hk<*^ z-|>q^H|h|?qS7%EMCcOr7qbl4!zquvzUiilXV#LQAm~7|8W^9oc?(7l>gH8MAn}7t zhz|5s{ierC`NR)fH!pu|Pf|#FMMK#pLeD686{FH4!gteJz=mME2s=jsp{VQ>p)H*t z*sQO%2y|NN4u^CKY?U;2mQN57Iz?z01y3!M1`#^Mf}zWq?MC2D2mPY(CJt_-3&Hc~ zrpQR+LE<-nV&VE(!7g+ccBJqRQwM9f61<4+{)`mv!!5j->BE1JeYo#u_`oX+-4IPh z7J>qN!~7jitjkWfu}O&&4Q=U&l{YPl_02pnzX~@3m4F3TPEZo*h);0rvUuG zl$8m22!gKoQ~kjlXa~NN$3R|!T@*WQtjGRDV=VF#1P%6h{}9;NjP6x9!w13t0bj@O zv?0LV#&$0FAP9f(67aYuTNqoJriCbc5d=NslB>TMbm8&SBA*1?@H61tkH?YOCqd8v z)rlPWPoSTbdxLL+m(T;`Sq7YNU~xVDmdoyp(ug?k23UpcN|_ax`m)ff`Ue#z(@))TrxV9KA_BvA_; zf`f}L4uTF5Iw&1#21_@wE>%gYLBv6%B}<`^MvItE3W8IILP5m-iS*u{YYn(YsZ{zK z%w%%FGr)BSHA{gjOimV^Ub@^1dz%(!pd^3Noks$g#T4@E*Cy4eS>Wm&lpW3YH`k%o$7jD~5$k?*D3JUg%pSOoUi{yzY>fOpm(14e-(*8c!{ovI?I z&y4{2wvYYGuH9{VA(?)gPyQUej3Tlcy#t7J8?m;A$OC_X1R$wQEo;~u)3C{Z7)vTs z%dH>)-WTwG3GeB^65bb@_ExZ~IcCTZSi{M_0D&^&p&8vrSQ>Uh^$y { + console.log(userPromised); userPromised .then(res => res.data._id) //get user ID .then(user_id => getSavedPins(user_id)) @@ -74,7 +73,7 @@ const getSavedPins = (user_id='') => { throw(err); }); -} +} //This function generates markers and drops them on a map (if specified) const makePinMarkers = (pinArray = []) => { From 5ee5e21b3594d9205d553c0fa0f2f59103edcdd9 Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Tue, 6 Mar 2018 13:19:38 -0500 Subject: [PATCH 03/31] feat: Preload saved pins of current user Use SavedPlaces.js function to fetch and drop user pins Although a working React component exists for the saved places, I use the function to deal with the asynchronicity of loading the maps. Sometimes the map loads after the components are rendered. Issue: #183 --- .../components/LeafletOsmMap/SavedPlaces.js | 19 ++++++++++++------- client/src/components/LeafletOsmMap/index.js | 4 ++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/client/src/components/LeafletOsmMap/SavedPlaces.js b/client/src/components/LeafletOsmMap/SavedPlaces.js index ff2c484..901ba3a 100644 --- a/client/src/components/LeafletOsmMap/SavedPlaces.js +++ b/client/src/components/LeafletOsmMap/SavedPlaces.js @@ -15,16 +15,17 @@ Full list of options: http://leafletjs.com/reference-1.3.0.html#icon const FAV_MARKER_ICON = L.icon({ iconUrl: '../../assets/icons/leaflet/marker-icon-fav-2x.png', className: 'favorites', - iconSize: [25, 41], + iconSize: [25, 41], //native aspect ratio: [28, 41] }); const CURRENT_USER = makeRequest('GET', 'user'); - + export default class SavedPlaces extends Component { constructor(props) { super(props) const {user, map} = props; + fetchAndDropUserPins(user, map); } @@ -43,7 +44,6 @@ export default class SavedPlaces extends Component { //Get and drop pins from any user on any map const fetchAndDropUserPins = (userPromised=CURRENT_USER, mapObj=undefined) => { - console.log(userPromised); userPromised .then(res => res.data._id) //get user ID .then(user_id => getSavedPins(user_id)) @@ -91,6 +91,8 @@ const makePinMarkers = (pinArray = []) => { title: pin.place_id }); + thisMarker.data = pin; //save the db data to the marker + pinMarkers.push(thisMarker); } @@ -114,13 +116,16 @@ const dropPin = (pinMarkers=[], mapObj=undefined) => { for (let marker of pinMarkers){ marker.addTo(mapObj); - - /* TO DO - Bind a custom container for each pin on click */ - marker.bindPopup(marker.title); + setPinPopup(marker); } } +/* TO DO + Create a custom container for each pin on click */ +const setPinPopup = (marker) => { + marker.bindPopup(marker.options.title); +} + //Export Statements export {fetchAndDropUserPins, getSavedPins, makePinMarkers, dropPin}; diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index 6d2a2e8..d580063 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -3,6 +3,7 @@ import style from "./style"; import MapPane from './MapPane'; import Search from '../../components/Search'; import SearchResults from '../../components/SearchResults'; +import {fetchAndDropUserPins} from './SavedPlaces.js'; /** * Leaflet related imports: leaflet, pouchdb module, and routing machine module @@ -64,6 +65,9 @@ export default class LeafletOSMMap extends Component { this.state.map.on('locationfound', this.onLocationFound); this.state.map.on('locationerror', this.onLocationError); this.state.map.on('click', this.onMapClick); + + //once map is ready, drop pins + fetchAndDropUserPins(undefined, this.state.map); } /** From 496f8d0a68826fb2659e7fb39045c3c9a5ee1d49 Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Tue, 6 Mar 2018 14:56:33 -0500 Subject: [PATCH 04/31] Outline 'GET ../user' error handling on preload pin Lower level functions via xhr request are throwing error for GET despite catch block on fetch promise. They need to be addressed in future code, so an outline was created with a possible solution for higher error handling. Issue # 183 --- .../components/LeafletOsmMap/SavedPlaces.js | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/client/src/components/LeafletOsmMap/SavedPlaces.js b/client/src/components/LeafletOsmMap/SavedPlaces.js index 901ba3a..23f9d71 100644 --- a/client/src/components/LeafletOsmMap/SavedPlaces.js +++ b/client/src/components/LeafletOsmMap/SavedPlaces.js @@ -17,7 +17,12 @@ const FAV_MARKER_ICON = L.icon({ className: 'favorites', iconSize: [25, 41], //native aspect ratio: [28, 41] }); -const CURRENT_USER = makeRequest('GET', 'user'); + + +const CURRENT_USER = makeRequest('GET', 'user') + .catch(err=>{ + //user not logged in + }); @@ -42,22 +47,44 @@ export default class SavedPlaces extends Component { */ //Get and drop pins from any user on any map -const fetchAndDropUserPins = (userPromised=CURRENT_USER, mapObj=undefined) => { +const fetchAndDropUserPins = (userPromised = CURRENT_USER, mapObj = undefined) => { userPromised - .then(res => res.data._id) //get user ID - .then(user_id => getSavedPins(user_id)) - .then(savedPins => { + .then(res => res.data._id) //get user ID + .then(user_id => getSavedPins(user_id)) + .then(savedPins => { - let pinMarkers = makePinMarkers(savedPins); - if (mapObj != null) dropPin(pinMarkers, mapObj); + let pinMarkers = makePinMarkers(savedPins); + if (mapObj != null) dropPin(pinMarkers, mapObj); + + }) + .catch(err => { + + /* + + //TO DO: + //Ensure all errors are relatd to user not being logged in + + //Make sure it's a server errror + if (!err.response) { + console.error(err); + return + }; + + //Determine which + switch (err.response.status) { + case 403: + //user not logged in + console.info('No places saved places, user not logged in'); + break; + + default: + //throw the error + console.errpr(err); + } */ + + }); - }) - .catch(err => { - //User not signed in, no saved places to load - console.log(`Error. abort load saved places: ${err}`); - }); - } const getSavedPins = (user_id='') => { From 69c67399653abdc3a2858e68c65857131eff9550 Mon Sep 17 00:00:00 2001 From: John Kwening Date: Wed, 7 Mar 2018 04:43:12 -0500 Subject: [PATCH 05/31] refactor: Style login and Register views Initial styling for login and register views per mockup --- client/src/components/AccountForm/index.js | 54 ++++++++++---- client/src/components/AccountForm/style.css | 79 +++++++++++++++++++++ client/src/routes/account/index.js | 2 +- client/src/routes/account/style.css | 14 ++-- 4 files changed, 129 insertions(+), 20 deletions(-) diff --git a/client/src/components/AccountForm/index.js b/client/src/components/AccountForm/index.js index 3707b4b..1fe4f6c 100644 --- a/client/src/components/AccountForm/index.js +++ b/client/src/components/AccountForm/index.js @@ -3,6 +3,7 @@ import style from './style.css'; import { handleSubmit, clearForms, setStateUserOrRedirectToSignIn } from "../../js/utilities"; import { LOGIN_PATH, REGISTER_PATH, RESET_PATH } from '../../../config'; import linkState from "linkstate"; +import { route } from 'preact-router'; export default class AccountForm extends Component { constructor() { @@ -14,6 +15,7 @@ export default class AccountForm extends Component { validatePasswordMap: this.createValidatePasswordMap(), }; this.handleSubmit = handleSubmit.bind(this); + this.routeToRegister = this.routeToRegister.bind(this); } createMessageMap = () => { @@ -66,27 +68,48 @@ export default class AccountForm extends Component { } } + routeToRegister() { + route("/register", true); + } + render({path},{ form_message, user, name, email, password, new_password, confirm_password }) { //DEFAULT TO LOGIN_PATH let form_header = "Sign In"; let name_input = ""; - let email_input =
Email:
; - let password_input =
Password:
; + let email_input = + ; + let password_input = + ; let new_password_input = ""; let confirm_password_input = ""; - let submit_button =
; - let link1 =

register

; - let link2 = ""; - // let link2 =

forgot password?

; + let submit_button = +
+ +
+ OR +
+ +
; + let link1 = ""; + let link2 =

forgot password?

; if(path === REGISTER_PATH){ form_header = "Register"; - name_input =
Name:
; - confirm_password_input =
Confirm password:
; - submit_button =
; - link1 =

Sign in

; + name_input = + ; + confirm_password_input = + ; + submit_button = ; + link1 =

Sign in

; + link2 = ""; } + if(path === RESET_PATH){ form_header = "Reset Password"; email_input =
Email: {user ? user.email : ''}
; @@ -95,13 +118,14 @@ export default class AccountForm extends Component { confirm_password_input =
Confirm new password:
; submit_button =
;; link1 = ""; + link2 = ""; } return ( -
-

{form_header}

+
+ Navi logo
{form_message}
-
-
+
+ {name_input} {email_input} {password_input} @@ -109,9 +133,9 @@ export default class AccountForm extends Component { {confirm_password_input} {submit_button} {link1} - {link2}
+ {link2}
); } diff --git a/client/src/components/AccountForm/style.css b/client/src/components/AccountForm/style.css index caa7917..8688dd3 100644 --- a/client/src/components/AccountForm/style.css +++ b/client/src/components/AccountForm/style.css @@ -3,4 +3,83 @@ padding: 5px; font-weight: bold; color: green; +} + +.inherit { + display: inherit; + height: inherit; + width: inherit; +} + +.logo { + display: inherit; + margin: auto; + padding: 2vh; +} + +.form { + display: grid; + padding: 5vh; + height: 70vh; + align-content: flex-start; +} + +.formChild { + display: block; + margin: 2vh auto; + width: 100%; + padding: 3vw; + border-color: lightslategray; + border-radius: 8px; + font-size: 1.2em; +} + +.strike { + display: block; + text-align: center; + overflow: hidden; + white-space: nowrap; +} + +.strike > span { + position: relative; + display: inline-block; + color: blue; +} + +.strike > span:before, +.strike > span:after { + content: ""; + position: absolute; + top: 50%; + width: 9999px; + height: 1px; + background: black; +} + +.strike > span:before { + right: 100%; + margin-right: 15px; +} + +.strike > span:after { + left: 100%; + margin-left: 15px; +} + +.link2 { + display: block; + position: fixed; + right: 0px; + padding: 2vh; + font-size: 1.1em; + color: blue; +} + +button { + background-color: turquoise; +} + +.regBtn { + background-color: darkcyan; } \ No newline at end of file diff --git a/client/src/routes/account/index.js b/client/src/routes/account/index.js index 961a1ff..6c5e5dc 100644 --- a/client/src/routes/account/index.js +++ b/client/src/routes/account/index.js @@ -29,7 +29,7 @@ export default class Account extends Component { } return (
-
+
{renderedForm}
diff --git a/client/src/routes/account/style.css b/client/src/routes/account/style.css index 9723eb7..8eefe33 100644 --- a/client/src/routes/account/style.css +++ b/client/src/routes/account/style.css @@ -1,8 +1,14 @@ -.signin { - padding: 56px 20px; - min-height: 100%; - width: 100%; +.inherit { + height: inherit; + width: inherit; + display: inherit; } .main { + display: block; + height: 93vh; + width: 100vw; + position: fixed; + top: 7vh; + background-color: snow; } From f09a76efd5f85dd332729c7369bfdeb57da3eeb2 Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Wed, 7 Mar 2018 08:01:41 -0500 Subject: [PATCH 06/31] refactor: Implement changes recommended by @jkwening LeafletOsmMap/index - Re-add the import function that was accidentally removed SavedPlaces - Refactor and rename to `src/js/saved-places` - Remove the GET request for user - Change input to fetchAndGetPins to user_id instead of promisedUser - Remove import of Leaflet module (function argument instead) Issue: #183, Pull Request #208 --- client/src/components/LeafletOsmMap/index.js | 6 +- client/src/js/saved-places.js | 113 +++++++++++++++++++ 2 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 client/src/js/saved-places.js diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index d580063..4de1573 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -3,7 +3,7 @@ import style from "./style"; import MapPane from './MapPane'; import Search from '../../components/Search'; import SearchResults from '../../components/SearchResults'; -import {fetchAndDropUserPins} from './SavedPlaces.js'; +import {fetchAndDropUserPins} from '../../js/saved-places'; /** * Leaflet related imports: leaflet, pouchdb module, and routing machine module @@ -66,8 +66,8 @@ export default class LeafletOSMMap extends Component { this.state.map.on('locationerror', this.onLocationError); this.state.map.on('click', this.onMapClick); - //once map is ready, drop pins - fetchAndDropUserPins(undefined, this.state.map); + //once map is ready, drop pins (user=undefined --> default) + fetchAndDropUserPins(undefined, this.state.map, L); } /** diff --git a/client/src/js/saved-places.js b/client/src/js/saved-places.js new file mode 100644 index 0000000..8a9fd8c --- /dev/null +++ b/client/src/js/saved-places.js @@ -0,0 +1,113 @@ +import {h, Component} from "preact"; +import {makeRequest} from "./server-requests-utils"; + + +/* Set all settings for saved place icon +Waiting for new icon for favorites +Full list of options: http://leafletjs.com/reference-1.3.0.html#icon + */ + +const FAV_MARKER_OPTIONS = { + iconUrl: '../../assets/icons/leaflet/marker-icon-fav-2x.png', + className: 'favorites', + iconSize: [25, 41], //native aspect ratio: [28, 41] +}; + + +/** + * Exported Functions + */ + +//Get and drop pins from any user on any map (all arguments are optional) +const fetchAndDropUserPins = (user_id, mapObj, L) => { + + const favMarker = L ? L.icon(FAV_MARKER_OPTIONS) : undefined; + + getSavedPins(user_id) + .then(savedPins => { + + if (!savedPins) return; + + let pinMarkers = makePinMarkers(savedPins, favMarker); + if (mapObj != null) dropPin(pinMarkers, mapObj); + + }) +} + +const getSavedPins = (user_id) => { + //GET 'search/savedpins/:user_id' + + return makeRequest('GET', 'savedPins', '', user_id) //pinsPromised + .then(res => res.data.savedPins) + .catch(err => { + // console.log(`Couldn't get the user pins: ${err}`); + }); + +} + +//This function generates markers and drops them on a map (if specified) +const makePinMarkers = (pinArray = [], icon) => { + + let pinMarkers = []; + + for (let pin of pinArray) { + //create marker for the pin and bind it ot the map + + let thisMarker = []; //the marker icon cannot be changed after the marker is created? + + if (icon) { //if (icon) thisMarker.icon = icon; doesn't work + thisMarker = L.marker([pin.lat, pin.lng], { + icon, + draggable: false, + autopan: true, + riseOnHover: true, + title: pin.place_id + }); + + } else { + thisMarker = L.marker([pin.lat, pin.lng], { + draggable: false, + autopan: true, + riseOnHover: true, + title: pin.place_id + }); + } + + thisMarker.data = pin; //save the db data to the marker + + pinMarkers.push(thisMarker); + } + + // console.log('User Pins added: ',pinMarkers) + return pinMarkers; + +} + +//This funciton drops pins on a map replacing pins if they already exist +const dropPin = (pinMarkers=[], mapObj=undefined) => { + + //if no map is defined, or there are no pins return + if ((mapObj == null) || (pinMarkers.length == 0)) return; + + /*TO DO?: + Do not allow duplication of pins, + Remove those that exist already on the old map + Hint: use sets + */ + + + for (let marker of pinMarkers){ + marker.addTo(mapObj); + setPinPopup(marker); + } +} + +/* TO DO + Create a custom container for each pin on click */ +const setPinPopup = (marker) => { + marker.bindPopup(marker.options.title); +} + + +//Export Statements +export {fetchAndDropUserPins, makePinMarkers, dropPin}; \ No newline at end of file From 080d7c44e6b5ab9b773a6fd6c22ec532f377d61a Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Wed, 7 Mar 2018 09:01:34 -0500 Subject: [PATCH 07/31] fix: change variable from const --- client/src/js/saved-places.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/js/saved-places.js b/client/src/js/saved-places.js index 8a9fd8c..638adeb 100644 --- a/client/src/js/saved-places.js +++ b/client/src/js/saved-places.js @@ -28,7 +28,7 @@ const fetchAndDropUserPins = (user_id, mapObj, L) => { if (!savedPins) return; - let pinMarkers = makePinMarkers(savedPins, favMarker); + const pinMarkers = makePinMarkers(savedPins, favMarker); if (mapObj != null) dropPin(pinMarkers, mapObj); }) @@ -110,4 +110,4 @@ const setPinPopup = (marker) => { //Export Statements -export {fetchAndDropUserPins, makePinMarkers, dropPin}; \ No newline at end of file +export {fetchAndDropUserPins, makePinMarkers, dropPin}; From 0c0aa75dff0a6b7f9b304514ec0e62ae0016a8ce Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Wed, 7 Mar 2018 09:12:16 -0500 Subject: [PATCH 08/31] fix: change variable type from let to const --- client/src/js/saved-places.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/js/saved-places.js b/client/src/js/saved-places.js index 638adeb..d1e8bb9 100644 --- a/client/src/js/saved-places.js +++ b/client/src/js/saved-places.js @@ -50,7 +50,7 @@ const makePinMarkers = (pinArray = [], icon) => { let pinMarkers = []; - for (let pin of pinArray) { + for (const pin of pinArray) { //create marker for the pin and bind it ot the map let thisMarker = []; //the marker icon cannot be changed after the marker is created? From 57d29147dc2139f0511b4853aae1ba378ff0c571 Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Wed, 7 Mar 2018 11:43:49 -0500 Subject: [PATCH 09/31] fix: Reinstate accidental deletion import module --- client/src/components/LeafletOsmMap/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index 41adb5a..a407884 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -3,6 +3,7 @@ import style from "./style"; import MapPane from './MapPane'; import Search from '../../components/Search'; import SearchResults from '../../components/SearchResults'; +import { makeRequest } from '../../js/server-requests-utils'; import {fetchAndDropUserPins} from '../../js/saved-places'; /** From 02d151ed97f84476759eeb9c72571722987518d4 Mon Sep 17 00:00:00 2001 From: Sameer Khan Date: Wed, 7 Mar 2018 13:53:02 -0500 Subject: [PATCH 10/31] Added a center button --- client/src/components/LeafletOsmMap/index.js | 101 +++++++++++++------ 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index 561aa19..d53f7de 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -1,5 +1,5 @@ -import { h, Component } from "preact"; -import style from "./style"; +import { h, Component } from 'preact'; +import style from './style'; import MapPane from './MapPane'; import Search from '../../components/Search'; import SearchResults from '../../components/SearchResults'; @@ -17,11 +17,12 @@ import Routing from '../../../node_modules/leaflet-routing-machine/src/index.js' * TIle layer configuration and attribution constants */ const OSM_URL = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; -const OSM_ATTRIB = '© OpenStreetMap contributors'; +const OSM_ATTRIB = + '© OpenStreetMap contributors'; const OSM_TILE_LAYER = new L.TileLayer(OSM_URL, { - attribution: OSM_ATTRIB, - useCache: true, - crossOrigin: true, + attribution: OSM_ATTRIB, + useCache: true, + crossOrigin: true }); // redirect marker icon path to assets directory @@ -33,8 +34,8 @@ export default class LeafletOSMMap extends Component { this.state = { map: null, mapCenter: null, - userMarker: null, - } + userMarker: null + }; this.onLocationFound = this.onLocationFound.bind(this); this.onLocationError = this.onLocationError.bind(this); this.onMapClick = this.onMapClick.bind(this); @@ -44,21 +45,24 @@ export default class LeafletOSMMap extends Component { // initialize map container if null if (!this.state.map) { this.setState({ - map: L.map('map', { - zoomControl: false, - zoom: 16, - }), + map: L.map('map', { + zoomControl: false, + zoom: 16 + }) }); } // add zoom to bottom left - const zoomControl = L.control.zoom().setPosition('bottomleft').addTo(this.state.map); + const zoomControl = L.control + .zoom() + .setPosition('bottomleft') + .addTo(this.state.map); this.state.map.addLayer(OSM_TILE_LAYER); // attempt to get user's current location via device this.state.map.locate({ setView: true, - enableHighAccuracy: true, + enableHighAccuracy: true }); // configure map events @@ -69,26 +73,56 @@ export default class LeafletOSMMap extends Component { /** * Handle leaflet map get device location event - * @param {*} event + * @param {*} event */ onLocationFound(event) { this.state.map.setZoom(16); const userMarker = L.circleMarker(event.latlng, { radius: 8, weight: 3, - fillColor: 'red', - }).addTo(this.state.map) + fillColor: 'red' + }) + .addTo(this.state.map) .bindPopup('You Are Here'); this.setState({ mapCenter: event.latlng, - userMarker: userMarker, + userMarker: userMarker + }); + + L.Control.Center = L.Control.extend({ + onAdd: function(map) { + let container = L.DomUtil.create( + 'div', + 'leaflet-bar leaflet-control leaflet-control-custom' + ); + + L.DomEvent.stopPropagation(container); + + container.style.backgroundColor = 'white'; + container.style.width = '50px'; + container.style.height = '50px'; + + L.DomEvent.on(container, 'click', function() { + map.flyTo(map._lastCenter); + }); + return container; + } }); + + L.control.center = function() { + return new L.Control.Center(); + }; + + L.control + .center() + .setPosition('bottomright') + .addTo(this.state.map); } /** * Handle leaflet map get device location failure - * @param {*} event + * @param {*} event */ onLocationError(event) { // TODO - dummy message for now if don't have permission to get user @@ -99,31 +133,33 @@ export default class LeafletOSMMap extends Component { /** * On map click event, add a marker to the map at the clicked location. * - * @param {*} event + * @param {*} event */ onMapClick(event) { const droppedPin = L.marker(event.latlng, { draggable: true, - autoPan: true, + autoPan: true }).addTo(this.state.map); const container = L.DomUtil.create('div'); const saveBtn = createButton('Save', container); const deleteBtn = createButton('Remove', container); - + L.DomEvent.on(saveBtn, 'click', function() { makeRequest('POST', 'savedPins', '', { lat: event.latlng.lat, - lng: event.latlng.lng, - }).then((response) => { - alert(`Succes: Saved pin at ${event.latlng} to db`); - console.log('Success - saved: ', response); - }).catch((err) => { - alert('Error saving pin: ', err); - console.log('Error saving pin: ', err); + lng: event.latlng.lng }) + .then(response => { + alert(`Succes: Saved pin at ${event.latlng} to db`); + console.log('Success - saved: ', response); + }) + .catch(err => { + alert('Error saving pin: ', err); + console.log('Error saving pin: ', err); + }); }); - + L.DomEvent.on(deleteBtn, 'click', function() { droppedPin.remove(); }); @@ -131,14 +167,13 @@ export default class LeafletOSMMap extends Component { droppedPin.bindPopup(container); } - render() { return (
- +
); } @@ -148,7 +183,7 @@ export default class LeafletOSMMap extends Component { // only needed for directions mode. // map.stopWatch(); this.state.map.remove(); - this.setState({map: null}); + this.setState({ map: null }); } } From 3a23041d658de510806bcaa927c4c4998a38cdee Mon Sep 17 00:00:00 2001 From: Sameer Khan Date: Wed, 7 Mar 2018 16:04:20 -0500 Subject: [PATCH 11/31] Prevented click event propogation --- client/src/components/LeafletOsmMap/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index d53f7de..27a9453 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -97,7 +97,7 @@ export default class LeafletOSMMap extends Component { 'leaflet-bar leaflet-control leaflet-control-custom' ); - L.DomEvent.stopPropagation(container); + L.DomEvent.disableClickPropagation(container); container.style.backgroundColor = 'white'; container.style.width = '50px'; From 4eebc979ee60ceb4d53f8066a62efa0d39c9a350 Mon Sep 17 00:00:00 2001 From: Sameer Khan Date: Wed, 7 Mar 2018 16:30:46 -0500 Subject: [PATCH 12/31] Added styles --- client/src/components/LeafletOsmMap/index.js | 30 ++++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index 27a9453..c348d13 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -97,11 +97,35 @@ export default class LeafletOSMMap extends Component { 'leaflet-bar leaflet-control leaflet-control-custom' ); + let controlText = L.DomUtil.create('div'); + controlText.style.color = 'rgb(25,25,25)'; + controlText.style.fontFamily = 'Roboto,Arial,sans-serif'; + controlText.style.fontSize = '16px'; + controlText.style.lineHeight = '38px'; + controlText.style.paddingLeft = '5px'; + controlText.style.paddingRight = '5px'; + controlText.innerHTML = 'Center Map'; + container.appendChild(controlText); + L.DomEvent.disableClickPropagation(container); - container.style.backgroundColor = 'white'; - container.style.width = '50px'; - container.style.height = '50px'; + container.style.backgroundColor = '#fff'; + container.style.border = '2px solid #e7e7e7'; + container.style.borderRadius = '3px'; + container.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)'; + container.style.cursor = 'pointer'; + container.style.marginBottom = '22px'; + container.style.textAlign = 'center'; + container.title = 'Click to recenter the map'; + + L.DomEvent.on(container, 'mouseenter', function(e) { + e.target.style.background = '#e7e7e7'; + }); + + L.DomEvent.on(container, 'mouseleave', function(e) { + // e.target.style.color = '#ccc'; + e.target.style.background = '#fff'; + }); L.DomEvent.on(container, 'click', function() { map.flyTo(map._lastCenter); From 7784299b4bfb6ba22e80a142f450072937e5ad41 Mon Sep 17 00:00:00 2001 From: seckboy Date: Wed, 7 Mar 2018 15:33:33 -0600 Subject: [PATCH 13/31] add saved pins and searches to profile --- client/config/dev.config.js | 2 + client/package-lock.json | 50 ++++++++-------- client/src/components/SavedPinsCard/index.js | 59 +++++++++++++++++++ client/src/components/SavedPinsCard/style.css | 21 +++++++ .../src/components/SearchHistoryCard/index.js | 59 +++++++++++++++++++ .../components/SearchHistoryCard/style.css | 21 +++++++ client/src/routes/profile/index.js | 8 ++- client/src/routes/profile/style.css | 12 +++- 8 files changed, 205 insertions(+), 27 deletions(-) create mode 100644 client/src/components/SavedPinsCard/index.js create mode 100644 client/src/components/SavedPinsCard/style.css create mode 100644 client/src/components/SearchHistoryCard/index.js create mode 100644 client/src/components/SearchHistoryCard/style.css diff --git a/client/config/dev.config.js b/client/config/dev.config.js index a6c725c..11b5769 100644 --- a/client/config/dev.config.js +++ b/client/config/dev.config.js @@ -4,4 +4,6 @@ module.exports = { REGISTER_PATH: '/users/register', LOGIN_PATH: '/users/login', RESET_PATH: '/users/reset-password', + SEARCH_HISTORY_PATH: '/search/history', + SAVED_PINS_PATH: '/search/savedpins', }; diff --git a/client/package-lock.json b/client/package-lock.json index c1beaf3..831e1c9 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -765,7 +765,7 @@ }, "ast-types-flow": { "version": "0.0.7", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, @@ -821,7 +821,7 @@ }, "axobject-query": { "version": "0.1.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/axobject-query/-/axobject-query-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz", "integrity": "sha1-YvWdvFnJ+SQnWco0mWDnov48NsA=", "dev": true, "requires": { @@ -2825,7 +2825,7 @@ }, "contains-path": { "version": "0.1.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/contains-path/-/contains-path-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, @@ -3379,7 +3379,7 @@ }, "damerau-levenshtein": { "version": "1.0.4", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", "dev": true }, @@ -4090,7 +4090,7 @@ }, "emoji-regex": { "version": "6.5.1", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/emoji-regex/-/emoji-regex-6.5.1.tgz", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz", "integrity": "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ==", "dev": true }, @@ -4336,7 +4336,7 @@ }, "eslint-config-airbnb": { "version": "16.1.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/eslint-config-airbnb/-/eslint-config-airbnb-16.1.0.tgz", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-16.1.0.tgz", "integrity": "sha512-zLyOhVWhzB/jwbz7IPSbkUuj7X2ox4PHXTcZkEmDqTvd0baJmJyuxlFPDlZOE/Y5bC+HQRaEkT3FoHo9wIdRiw==", "dev": true, "requires": { @@ -4345,7 +4345,7 @@ }, "eslint-config-airbnb-base": { "version": "12.1.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz", "integrity": "sha512-/vjm0Px5ZCpmJqnjIzcFb9TKZrKWz0gnuG/7Gfkt0Db1ELJR51xkZth+t14rYdqWgX836XbuxtArbIHlVhbLBA==", "dev": true, "requires": { @@ -4354,7 +4354,7 @@ }, "eslint-import-resolver-node": { "version": "0.3.2", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, "requires": { @@ -4364,7 +4364,7 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/debug/-/debug-2.6.9.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { @@ -4375,7 +4375,7 @@ }, "eslint-module-utils": { "version": "2.1.1", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", "dev": true, "requires": { @@ -4385,7 +4385,7 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/debug/-/debug-2.6.9.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { @@ -4394,7 +4394,7 @@ }, "find-up": { "version": "1.1.2", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/find-up/-/find-up-1.1.2.tgz", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { @@ -4404,7 +4404,7 @@ }, "path-exists": { "version": "2.1.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/path-exists/-/path-exists-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { @@ -4413,7 +4413,7 @@ }, "pkg-dir": { "version": "1.0.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/pkg-dir/-/pkg-dir-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { @@ -4442,7 +4442,7 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/debug/-/debug-2.6.9.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { @@ -4451,7 +4451,7 @@ }, "doctrine": { "version": "1.5.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/doctrine/-/doctrine-1.5.0.tgz", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { @@ -4461,7 +4461,7 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { @@ -4473,7 +4473,7 @@ }, "path-type": { "version": "2.0.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/path-type/-/path-type-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { @@ -4482,7 +4482,7 @@ }, "read-pkg": { "version": "2.0.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/read-pkg/-/read-pkg-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { @@ -4493,7 +4493,7 @@ }, "read-pkg-up": { "version": "2.0.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { @@ -4503,7 +4503,7 @@ }, "strip-bom": { "version": "3.0.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/strip-bom/-/strip-bom-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true } @@ -4555,7 +4555,7 @@ }, "eslint-restricted-globals": { "version": "0.1.1", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", "dev": true }, @@ -7771,7 +7771,7 @@ }, "lodash.cond": { "version": "4.5.2", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/lodash.cond/-/lodash.cond-4.5.2.tgz", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", "dev": true }, @@ -9454,7 +9454,7 @@ }, "path-parse": { "version": "1.0.5", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/path-parse/-/path-parse-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, @@ -12402,7 +12402,7 @@ }, "resolve": { "version": "1.5.0", - "resolved": "https://bcitllc.pkgs.visualstudio.com/_packaging/BcitPackages/npm/registry/resolve/-/resolve-1.5.0.tgz", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", "dev": true, "requires": { diff --git a/client/src/components/SavedPinsCard/index.js b/client/src/components/SavedPinsCard/index.js new file mode 100644 index 0000000..1e7f808 --- /dev/null +++ b/client/src/components/SavedPinsCard/index.js @@ -0,0 +1,59 @@ +import {h, Component} from 'preact'; +import style from './style'; +import {makeRequest, token} from "../../js/server-requests-utils"; +import {SAVED_PINS_PATH} from '../../../config'; + +export default class SavedPinsCard extends Component { + constructor() { + super(); + this.state = { + user: {}, + savedPins: [], + }; + this.getSavedPins = this.getSavedPins.bind(this); + this.displayPins = this.displayPins.bind(this); + } + + componentWillMount() { + this.setState({user: this.props.user}); + this.getSavedPins(); + } + + displayPins(savedPins) { + let pins = []; + savedPins.map( pin => { + pins.push(
{pin.place_id}
); + }); + if(pins.length == 0) pins.push(
No saved pins
); + this.setState({pins: pins}); + } + + getSavedPins() { + makeRequest('GET', SAVED_PINS_PATH) + .then(function (response) { + this.displayPins(response.data.savedPins); + }.bind(this)) + .catch(function (error) { + if (error.response === undefined) { + this.setState({savedPins: error}); + } else { + this.setState({savedPins: error.response.data}); + } + }.bind(this)); + } + + render({}, {user, pins}) { + + + return ( +
+ + Saved Pins
+ + +
{pins}
+ +
+ ); + } +} diff --git a/client/src/components/SavedPinsCard/style.css b/client/src/components/SavedPinsCard/style.css new file mode 100644 index 0000000..1e4ce8b --- /dev/null +++ b/client/src/components/SavedPinsCard/style.css @@ -0,0 +1,21 @@ +.savedPinsCard { + border-radius: 3px; + border-width: 2px; + border-style: groove; + margin-bottom: 10px; + padding-left: 5px; +} + +#savedPinsCardTitle { + display: block; + font-size: 1em; + font-weight: bold; + text-align: center; + color: purple; + margin: 0 auto; +} + +.savedPinsContainer{ + text-align: center; +} + diff --git a/client/src/components/SearchHistoryCard/index.js b/client/src/components/SearchHistoryCard/index.js new file mode 100644 index 0000000..0434529 --- /dev/null +++ b/client/src/components/SearchHistoryCard/index.js @@ -0,0 +1,59 @@ +import {h, Component} from 'preact'; +import style from './style'; +import {makeRequest, token} from "../../js/server-requests-utils"; +import {SEARCH_HISTORY_PATH} from '../../../config'; + +export default class SearchHistoryCard extends Component { + constructor() { + super(); + this.state = { + user: {}, + searchHistory: [], + }; + this.getSearchHistory = this.getSearchHistory.bind(this); + this.displayHistory = this.displayHistory.bind(this); + } + + componentWillMount() { + this.setState({user: this.props.user}); + this.getSearchHistory(); + } + + displayHistory(searchHistory) { + let histories = []; + searchHistory.map( search => { + histories.push(
{search.query}
); + }); + if(histories.length == 0) histories.push(
No saved searches
); + this.setState({histories: histories}); + } + + getSearchHistory() { + makeRequest('GET', SEARCH_HISTORY_PATH) + .then(function (response) { + this.displayHistory(response.data.searchHistory); + }.bind(this)) + .catch(function (error) { + if (error.response === undefined) { + this.setState({searchHistory: error}); + } else { + this.setState({searchHistory: error.response.data}); + } + }.bind(this)); + } + + render({}, {user, histories}) { + + + return ( +
+ + Search History
+ + +
{histories}
+ +
+ ); + } +} diff --git a/client/src/components/SearchHistoryCard/style.css b/client/src/components/SearchHistoryCard/style.css new file mode 100644 index 0000000..006d3df --- /dev/null +++ b/client/src/components/SearchHistoryCard/style.css @@ -0,0 +1,21 @@ +.searchHistoryCard { + border-radius: 3px; + border-width: 2px; + border-style: groove; + margin-bottom: 10px; + padding-left: 5px; +} + +#searchHistoryCardTitle { + display: block; + font-size: 1em; + font-weight: bold; + text-align: center; + color: purple; + margin: 0 auto; +} + +.searchHistoriesContainer{ + text-align: center; +} + diff --git a/client/src/routes/profile/index.js b/client/src/routes/profile/index.js index 61cdc78..2ac68b3 100644 --- a/client/src/routes/profile/index.js +++ b/client/src/routes/profile/index.js @@ -5,6 +5,8 @@ import Logo from '../../components/Logo'; import ProfileCard from '../../components/ProfileCard'; import ProfileEditForm from '../../components/ProfileEditForm'; import ProfileSettingsForm from '../../components/ProfileSettingsForm'; +import SavedPinsCard from '../../components/SavedPinsCard'; +import SearchHistoryCard from '../../components/SearchHistoryCard'; import {setStateUserOrRedirectToSignIn} from "../../js/utilities"; export default class Profile extends Component { @@ -23,11 +25,15 @@ render({success}, {user, time}) { return (
- {success} +
{success}
+ + +
); } diff --git a/client/src/routes/profile/style.css b/client/src/routes/profile/style.css index cc0c206..756d6bf 100644 --- a/client/src/routes/profile/style.css +++ b/client/src/routes/profile/style.css @@ -4,10 +4,20 @@ width: 100%; } +.successMessage{ + text-align: center; + font-weight: bold; + padding: 5px; +} + .link { padding: 5px; } .link a { text-decoration: none; -} \ No newline at end of file +} + +.links_container{ + text-align: center; +} From 651dce4e5fb596085b5ddbf93fa361e6d1bb927e Mon Sep 17 00:00:00 2001 From: John Kwening Date: Wed, 7 Mar 2018 16:54:26 -0500 Subject: [PATCH 14/31] refactor: Remove SavedPlaces.js duplicate --- .../components/LeafletOsmMap/SavedPlaces.js | 159 ------------------ 1 file changed, 159 deletions(-) delete mode 100644 client/src/components/LeafletOsmMap/SavedPlaces.js diff --git a/client/src/components/LeafletOsmMap/SavedPlaces.js b/client/src/components/LeafletOsmMap/SavedPlaces.js deleted file mode 100644 index 23f9d71..0000000 --- a/client/src/components/LeafletOsmMap/SavedPlaces.js +++ /dev/null @@ -1,159 +0,0 @@ -import {h, Component} from "preact"; -import {makeRequest} from "../../js/server-requests-utils"; - -/** - * Leaflet related imports: leaflet, pouchdb module, and routing machine module - */ -import '../../../node_modules/leaflet/dist/leaflet.css'; -import '../../../node_modules/leaflet-routing-machine/dist/leaflet-routing-machine.css'; -import L from '../../js/leaflet-tileLayer-pouchdb-cached'; - -/* Set all settings for saved place icon -Waiting for new icon for favorites -Full list of options: http://leafletjs.com/reference-1.3.0.html#icon - */ -const FAV_MARKER_ICON = L.icon({ - iconUrl: '../../assets/icons/leaflet/marker-icon-fav-2x.png', - className: 'favorites', - iconSize: [25, 41], //native aspect ratio: [28, 41] -}); - - -const CURRENT_USER = makeRequest('GET', 'user') - .catch(err=>{ - //user not logged in - }); - - - -export default class SavedPlaces extends Component { - constructor(props) { - super(props) - const {user, map} = props; - - fetchAndDropUserPins(user, map); - } - - render() { - //This shouldn't render much (if anything) - return ( null ); - } - -} - - -/** - * Exported Functions - */ - -//Get and drop pins from any user on any map -const fetchAndDropUserPins = (userPromised = CURRENT_USER, mapObj = undefined) => { - - userPromised - .then(res => res.data._id) //get user ID - .then(user_id => getSavedPins(user_id)) - .then(savedPins => { - - let pinMarkers = makePinMarkers(savedPins); - if (mapObj != null) dropPin(pinMarkers, mapObj); - - }) - .catch(err => { - - /* - - //TO DO: - //Ensure all errors are relatd to user not being logged in - - //Make sure it's a server errror - if (!err.response) { - console.error(err); - return - }; - - //Determine which - switch (err.response.status) { - case 403: - //user not logged in - console.info('No places saved places, user not logged in'); - break; - - default: - //throw the error - console.errpr(err); - } */ - - }); - -} - -const getSavedPins = (user_id='') => { - //GET 'search/savedpins/:user_id' - let pinsPromised = makeRequest('GET', 'savedPins', '', user_id); - - return pinsPromised - .then(res => res.data.savedPins) - .catch(err => { - // console.log(`Couldn't get the user pins: ${err}`); - - //rethrow error - throw(err); - }); - -} - -//This function generates markers and drops them on a map (if specified) -const makePinMarkers = (pinArray = []) => { - - let pinMarkers = []; - - - for (let pin of pinArray) { - //create marker for the pin and bind it ot the map - let thisMarker = L.marker([pin.lat, pin.lng], { - icon: FAV_MARKER_ICON, - draggable: false, - autopan: true, - riseOnHover: true, - title: pin.place_id - }); - - thisMarker.data = pin; //save the db data to the marker - - pinMarkers.push(thisMarker); - } - - // console.log('User Pins added: ',pinMarkers) - return pinMarkers; - -} - -//This funciton drops pins on a map replacing pins if they already exist -const dropPin = (pinMarkers=[], mapObj=undefined) => { - - //if no map is defined, or there are no pins return - if ((mapObj == null) || (pinMarkers.length == 0)) return; - - /*TO DO?: - Do not allow duplication of pins, - Remove those that exist already on the old map - Hint: use sets - */ - - - for (let marker of pinMarkers){ - marker.addTo(mapObj); - setPinPopup(marker); - } -} - -/* TO DO - Create a custom container for each pin on click */ -const setPinPopup = (marker) => { - marker.bindPopup(marker.options.title); -} - - -//Export Statements -export {fetchAndDropUserPins, getSavedPins, makePinMarkers, dropPin}; - From c9c465e6a6cecbb0d60fc3ad08b83a69fa5035f3 Mon Sep 17 00:00:00 2001 From: Sameer Khan Date: Wed, 7 Mar 2018 18:05:39 -0500 Subject: [PATCH 15/31] Set view changed --- client/src/components/LeafletOsmMap/index.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index c348d13..2bad09e 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -91,13 +91,15 @@ export default class LeafletOSMMap extends Component { }); L.Control.Center = L.Control.extend({ - onAdd: function(map) { - let container = L.DomUtil.create( + onAdd: map => { + const center = this.state.mapCenter; + const zoom = map.options.zoom; + const container = L.DomUtil.create( 'div', 'leaflet-bar leaflet-control leaflet-control-custom' ); - let controlText = L.DomUtil.create('div'); + const controlText = L.DomUtil.create('div'); controlText.style.color = 'rgb(25,25,25)'; controlText.style.fontFamily = 'Roboto,Arial,sans-serif'; controlText.style.fontSize = '16px'; @@ -126,16 +128,15 @@ export default class LeafletOSMMap extends Component { // e.target.style.color = '#ccc'; e.target.style.background = '#fff'; }); - L.DomEvent.on(container, 'click', function() { - map.flyTo(map._lastCenter); + map.setView(center, zoom); }); return container; } }); - L.control.center = function() { - return new L.Control.Center(); + L.control.center = function(opts) { + return new L.Control.Center(opts); }; L.control From 9a617f9865d75f29c1e86255d572130a4580fada Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Wed, 7 Mar 2018 18:58:10 -0500 Subject: [PATCH 16/31] feat: Check for pin duplication before saving After a new pin posts, check to see if it already exists. If the pin exists, send a 400 error to the client with a message saying "Duplicate Pin" and the original pin db object Issue: #204 --- controllers/saved-pins-controller.js | 42 ++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/controllers/saved-pins-controller.js b/controllers/saved-pins-controller.js index b346151..f53e0a1 100644 --- a/controllers/saved-pins-controller.js +++ b/controllers/saved-pins-controller.js @@ -60,18 +60,38 @@ exports.getSavedPinsById = (appReq, appRes) => { * @param {string} appReq.body.place_id - name of pin location */ exports.postSavedPins = (appReq, appRes) => { - const savedPin = new SavedPins({ - lat: appReq.body.lat, - lng: appReq.body.lng, - place_id: appReq.body.place_id, - user: appReq.userId, // authenticated user's id - }); - savedPin.save().then((pin) => { - appRes.send({ pin }); - }, (e) => { - appRes.status(500).send(e); - }); + //ensure not duplicate first + SavedPins.find({ user: appReq.userId }) + .then(savedPins => { + //check to see if the pin already exists + return savedPins.filter(pin => { + return (pin.lat == appReq.body.lat) && (pin.lng == appReq.body.lng) + }); + + }) + .then(duplicatePins => { + + if (duplicatePins.length > 0) { + appRes.status(400).send({ duplicatePin: duplicatePins, message: 'Duplicate found. Pin not saved.' }); + return + } + + const newPin = new SavedPins({ + lat: appReq.body.lat, + lng: appReq.body.lng, + place_id: appReq.body.place_id, + user: appReq.userId, // authenticated user's id + }); + + newPin.save().then((pin) => { + appRes.send({ pin }); + }, (e) => { + appRes.status(500).send(e); + }); + + + }) }; /** From be2d8d070121084d3c60a14e2fafebdc83d0bc69 Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Wed, 7 Mar 2018 22:58:08 -0500 Subject: [PATCH 17/31] feat: Create handler for post new pin errors If pin duplicate, alert user. If not signed in, suggest sign in. Issue: #204 --- client/src/components/LeafletOsmMap/index.js | 28 ++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index a407884..e60c1bb 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -1,4 +1,5 @@ import { h, Component } from "preact"; +import { route } from "preact-router"; import style from "./style"; import MapPane from './MapPane'; import Search from '../../components/Search'; @@ -120,11 +121,34 @@ export default class LeafletOSMMap extends Component { lat: event.latlng.lat, lng: event.latlng.lng, }).then((response) => { + alert(`Succes: Saved pin at ${event.latlng} to db`); console.log('Success - saved: ', response); + //convert the pinh }).catch((err) => { - alert('Error saving pin: ', err); - console.log('Error saving pin: ', err); + + switch (err.response.status){ + case 400: //duplicate pin + const origPin = err.response.data; + alert('This pin is already on your map.'); + /*TO DO: + Convert popup alert to toast message + */ + break; + case 403: //user not signed in + /*TO DO: + Convert to overlay/lightbox window to sign up form + */ + if (confirm("Would you like to sign in to save places?")) { + route('/signin', true); + } + + break; + default: + console.log(err); //error saving pin + + } + }) }); From d6afc1758cc3a592432b4faaf5af893025a987bc Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Wed, 7 Mar 2018 23:08:09 -0500 Subject: [PATCH 18/31] fix: Add additional argument to makePinMarker Modified saved-places.js utility to handle input of L without fetchAndDropPin Issue: #204 --- client/src/js/saved-places.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/js/saved-places.js b/client/src/js/saved-places.js index d1e8bb9..cb005d2 100644 --- a/client/src/js/saved-places.js +++ b/client/src/js/saved-places.js @@ -46,8 +46,10 @@ const getSavedPins = (user_id) => { } //This function generates markers and drops them on a map (if specified) -const makePinMarkers = (pinArray = [], icon) => { +const makePinMarkers = (pinArray = [], icon, L) => { + const icon = (L && !icon) ? L.icon(FAV_MARKER_OPTIONS) : icon; + let pinMarkers = []; for (const pin of pinArray) { From ea3f79b8e23eea1356fa490addc6d3fe7dde7bfe Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Thu, 8 Mar 2018 00:37:55 -0500 Subject: [PATCH 19/31] refactor: makePinMarkers to serve pins externally Refactor (slightly) makePinMarkers to optimize for external use Issue: #204 --- client/src/js/saved-places.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/src/js/saved-places.js b/client/src/js/saved-places.js index cb005d2..4e9f1e5 100644 --- a/client/src/js/saved-places.js +++ b/client/src/js/saved-places.js @@ -20,15 +20,13 @@ const FAV_MARKER_OPTIONS = { //Get and drop pins from any user on any map (all arguments are optional) const fetchAndDropUserPins = (user_id, mapObj, L) => { - - const favMarker = L ? L.icon(FAV_MARKER_OPTIONS) : undefined; getSavedPins(user_id) .then(savedPins => { if (!savedPins) return; - const pinMarkers = makePinMarkers(savedPins, favMarker); + const pinMarkers = makePinMarkers(savedPins, L); if (mapObj != null) dropPin(pinMarkers, mapObj); }) @@ -46,9 +44,9 @@ const getSavedPins = (user_id) => { } //This function generates markers and drops them on a map (if specified) -const makePinMarkers = (pinArray = [], icon, L) => { +const makePinMarkers = (pinArray = [], L, markerOptions=FAV_MARKER_OPTIONS) => { - const icon = (L && !icon) ? L.icon(FAV_MARKER_OPTIONS) : icon; + const icon = L ? L.icon(FAV_MARKER_OPTIONS) : undefined; let pinMarkers = []; From 8bb39a9c697350669e3efebb58a835370cde242e Mon Sep 17 00:00:00 2001 From: Siobhan Williams Date: Thu, 8 Mar 2018 00:40:36 -0500 Subject: [PATCH 20/31] feat: Switch newly saved pin to favorites icon Convert a pin to favorite icon after it posts successfully. Pin shifts slightly so this will need to be addressed in another issue Issue: #204 --- client/src/components/LeafletOsmMap/index.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index e60c1bb..9c7de88 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -5,7 +5,7 @@ import MapPane from './MapPane'; import Search from '../../components/Search'; import SearchResults from '../../components/SearchResults'; import { makeRequest } from '../../js/server-requests-utils'; -import {fetchAndDropUserPins} from '../../js/saved-places'; +import {fetchAndDropUserPins, makePinMarkers, dropPin} from '../../js/saved-places'; /** * Leaflet related imports: leaflet, pouchdb module, and routing machine module @@ -115,16 +115,22 @@ export default class LeafletOSMMap extends Component { const container = L.DomUtil.create('div'); const saveBtn = createButton('Save', container); const deleteBtn = createButton('Remove', container); - - L.DomEvent.on(saveBtn, 'click', function() { + + L.DomEvent.on(saveBtn, 'click', function () { makeRequest('POST', 'savedPins', '', { lat: event.latlng.lat, lng: event.latlng.lng, }).then((response) => { - alert(`Succes: Saved pin at ${event.latlng} to db`); - console.log('Success - saved: ', response); - //convert the pinh + //remove old icon + droppedPin.remove() + + //add a new one + const savedMarker = makePinMarkers([response.data.pin], L); + dropPin(savedMarker, event.target); + + // alert(`Succes: Saved pin at ${event.latlng} to db`); + }).catch((err) => { switch (err.response.status){ From 8b001f038cd20377cc1584fb4331f6e202bdb6a1 Mon Sep 17 00:00:00 2001 From: John Kwening Date: Fri, 9 Mar 2018 20:18:33 -0500 Subject: [PATCH 21/31] feat: Add basic Navbar style --- client/src/components/Nav/index.js | 29 ++--------------------------- client/src/components/Nav/style.css | 28 ++++++++++------------------ client/src/components/app.js | 1 + 3 files changed, 13 insertions(+), 45 deletions(-) diff --git a/client/src/components/Nav/index.js b/client/src/components/Nav/index.js index d283520..93d422b 100644 --- a/client/src/components/Nav/index.js +++ b/client/src/components/Nav/index.js @@ -4,38 +4,13 @@ import style from './style.css'; export default class Nav extends Component { componentDidMount() { - let navIcon = document.getElementsByClassName(style.navIcon)[0]; - let linkContainer = document.getElementsByClassName(style.linkContainer)[0]; - linkContainer.style.display = "none"; - navIcon.onclick = function (e) { - e.preventDefault(); - var x = linkContainer; - if (x.style.display === "block") { - x.style.display = "none"; - } else { - x.style.display = "block"; - } - return false; - } - - let links = document.getElementsByClassName(style.link); - for (let link of links) { - link.onclick = function () { - linkContainer.style.display = "none"; - } - } } render() { return (
- - + Home screen icon + Profile page icon
); } diff --git a/client/src/components/Nav/style.css b/client/src/components/Nav/style.css index 0477ac8..3cc79bd 100644 --- a/client/src/components/Nav/style.css +++ b/client/src/components/Nav/style.css @@ -1,26 +1,18 @@ .nav { width: 100%; height: 5vh; + background: linear-gradient(to right, #5A98A1,#2c5b61); + display: block; } -.navIcon{ - height: 40px; - background-color:white; - position: relative; - top: 50%; - transform: translateY(-50%); - padding: 10px; +.profileIcon { + padding: 2vw; + height: inherit; + position: fixed; + right: 0px; } -.linkContainer{ - display: none; - background-color: white; - position: absolute; - top: 40px; - padding: 10px; - z-index:1; -} - -.link{ - +.homeIcon { + padding: 2vw; + height: inherit; } \ No newline at end of file diff --git a/client/src/components/app.js b/client/src/components/app.js index 5d661f4..44dc1fe 100644 --- a/client/src/components/app.js +++ b/client/src/components/app.js @@ -39,6 +39,7 @@ export default class App extends Component { ) } +
; - let link1 = ""; let link2 =

forgot password?

; if(path === REGISTER_PATH){ @@ -106,7 +105,6 @@ export default class AccountForm extends Component { ; submit_button = ; - link1 =

Sign in

; link2 = ""; } @@ -117,7 +115,6 @@ export default class AccountForm extends Component { new_password_input =
New password:
; confirm_password_input =
Confirm new password:
; submit_button =
;; - link1 = ""; link2 = ""; } return ( @@ -132,7 +129,6 @@ export default class AccountForm extends Component { {new_password_input} {confirm_password_input} {submit_button} - {link1}
{link2} diff --git a/client/src/components/AccountForm/style.css b/client/src/components/AccountForm/style.css index 8688dd3..a3f7d12 100644 --- a/client/src/components/AccountForm/style.css +++ b/client/src/components/AccountForm/style.css @@ -70,16 +70,16 @@ .link2 { display: block; position: fixed; - right: 0px; - padding: 2vh; + right: 5vw; + bottom: 1vh; font-size: 1.1em; color: blue; } button { - background-color: turquoise; + background-color: #5A98A1; } .regBtn { - background-color: darkcyan; + background-color: #2c5b61; } \ No newline at end of file diff --git a/client/src/components/LeafletOsmMap/MapPane.js b/client/src/components/LeafletOsmMap/MapPane.js index d259697..3a0412b 100644 --- a/client/src/components/LeafletOsmMap/MapPane.js +++ b/client/src/components/LeafletOsmMap/MapPane.js @@ -3,7 +3,7 @@ import { h, Component } from 'preact'; export default class MapPane extends Component { render() { const styles = { - height: this.props.height, // HAVE TO SET HEIGHT TO RENDER MAP + height: this.props.paneHeight, // HAVE TO SET HEIGHT TO RENDER MAP } return (
diff --git a/client/src/components/LeafletOsmMap/index.js b/client/src/components/LeafletOsmMap/index.js index 854bc9b..29def97 100644 --- a/client/src/components/LeafletOsmMap/index.js +++ b/client/src/components/LeafletOsmMap/index.js @@ -230,7 +230,7 @@ export default class LeafletOSMMap extends Component { - +
); } diff --git a/client/src/components/Nav/index.js b/client/src/components/Nav/index.js index 3522c66..9ba4f62 100644 --- a/client/src/components/Nav/index.js +++ b/client/src/components/Nav/index.js @@ -19,8 +19,11 @@ export default class Nav extends Component { }; render() { + const styles = { + height: this.props.navHeight, + } return ( -
+
Home screen icon Profile page icon ) } -
); diff --git a/client/src/routes/account/index.js b/client/src/routes/account/index.js index 6c5e5dc..5ff98ff 100644 --- a/client/src/routes/account/index.js +++ b/client/src/routes/account/index.js @@ -27,11 +27,14 @@ export default class Account extends Component { ) } + + const styles = { + height: this.props.paneHeight + } + return ( -
-
- {renderedForm} -
+
+ {renderedForm}
); } diff --git a/client/src/routes/account/style.css b/client/src/routes/account/style.css index 8eefe33..c8fa6aa 100644 --- a/client/src/routes/account/style.css +++ b/client/src/routes/account/style.css @@ -6,7 +6,6 @@ .main { display: block; - height: 93vh; width: 100vw; position: fixed; top: 7vh; diff --git a/client/src/routes/maps/index.js b/client/src/routes/maps/index.js index 16b5a50..2c71388 100644 --- a/client/src/routes/maps/index.js +++ b/client/src/routes/maps/index.js @@ -6,7 +6,7 @@ export default class MapExplorer extends Component { render() { return (
- +
); } diff --git a/client/src/routes/maps/style.css b/client/src/routes/maps/style.css index 9070e0b..2c69558 100644 --- a/client/src/routes/maps/style.css +++ b/client/src/routes/maps/style.css @@ -1,5 +1,4 @@ .maps { width: 100vw; - height: 95vh; display: block; } \ No newline at end of file From 55b37ecce9ded491bfd028ee7590e9badd38b5d9 Mon Sep 17 00:00:00 2001 From: John Kwening Date: Fri, 9 Mar 2018 23:44:32 -0500 Subject: [PATCH 24/31] refactor: Style home page per mockup --- client/src/components/app.js | 7 +---- client/src/routes/home/index.js | 29 ++++++++++++++++++-- client/src/routes/home/style.css | 47 +++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/client/src/components/app.js b/client/src/components/app.js index 490e310..cb42d4a 100644 --- a/client/src/components/app.js +++ b/client/src/components/app.js @@ -40,14 +40,9 @@ export default class App extends Component { render() { return (
- - { ({ matches, path, url }) => matches && ( - - ) } -

Where can we take you today?

- +
diff --git a/client/src/routes/home/style.css b/client/src/routes/home/style.css index 881ba3c..06dfee9 100644 --- a/client/src/routes/home/style.css +++ b/client/src/routes/home/style.css @@ -29,7 +29,7 @@ font-size: 1.2em; } -.searchBar { +.search > form { position: static; } From cde8e97fadda0f8afad7ee50739dca17d353f074 Mon Sep 17 00:00:00 2001 From: John Kwening Date: Sat, 10 Mar 2018 10:06:28 -0500 Subject: [PATCH 29/31] refactor: Style reset-password page --- .../components/ForgotPasswordForm/index.js | 19 ++++----- .../components/ForgotPasswordForm/style.css | 42 ++++++++++++++++++- client/src/components/app.js | 2 +- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/client/src/components/ForgotPasswordForm/index.js b/client/src/components/ForgotPasswordForm/index.js index 1a83853..80b1841 100644 --- a/client/src/components/ForgotPasswordForm/index.js +++ b/client/src/components/ForgotPasswordForm/index.js @@ -5,17 +5,16 @@ import style from './style'; export default class ForgotPasswordForm extends Component { render() { - return (
- -

We will send you a temporary password, enter your email address

-
- Email:
-
- + return ( +
+

Forgot Your Password?

+

Enter your email address below to reset your password.

+ + + - register -
- sign in +

Not a member? Sign up!

); } } diff --git a/client/src/components/ForgotPasswordForm/style.css b/client/src/components/ForgotPasswordForm/style.css index 7a68d82..4dd1649 100644 --- a/client/src/components/ForgotPasswordForm/style.css +++ b/client/src/components/ForgotPasswordForm/style.css @@ -1,5 +1,43 @@ .forgot-password-form { - padding: 56px 20px; - min-height: 100%; + width: inherit; + height: inherit; + margin-top: 15vh; +} + +.forgot-password-form > h2 { + margin: auto; + text-align: center; +} + +.forgot-password-form > p { + padding: 3vw; + text-align: center; + font-size: 1.1em; +} + +.form { + display: grid; + padding: 0 5vh; + align-content: flex-start; +} + +.formChild { + display: block; + margin: 2vh auto; width: 100%; + padding: 3vw; + border-color: lightslategray; + border-radius: 8px; + font-size: 1.2em; +} + +.register { + display: block; + position: fixed; + bottom: 5vh; +} + +.register > p { + text-align: center; } + diff --git a/client/src/components/app.js b/client/src/components/app.js index cb42d4a..94a4e5a 100644 --- a/client/src/components/app.js +++ b/client/src/components/app.js @@ -49,7 +49,7 @@ export default class App extends Component { - + From 5f8f369e5136b55b6cd57244151e71aca3efc32c Mon Sep 17 00:00:00 2001 From: John Kwening Date: Sat, 10 Mar 2018 12:41:49 -0500 Subject: [PATCH 30/31] refactor: Add user info to profile --- client/src/components/Logo/index.js | 2 +- client/src/routes/profile/index.js | 14 ++++++++++---- client/src/routes/profile/style.css | 12 ++++++++++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/client/src/components/Logo/index.js b/client/src/components/Logo/index.js index b35b49a..0a2e047 100644 --- a/client/src/components/Logo/index.js +++ b/client/src/components/Logo/index.js @@ -8,7 +8,7 @@ export default class Logo extends Component { return (
-

Welcome to {APP_NAME}

+

Welcome!

); } diff --git a/client/src/routes/profile/index.js b/client/src/routes/profile/index.js index 2ac68b3..3f302af 100644 --- a/client/src/routes/profile/index.js +++ b/client/src/routes/profile/index.js @@ -26,13 +26,19 @@ render({success}, {user, time}) {
{success}
+
+
+ User Info + Name: {user.name}
+ Email: {user.email}
+
+
); diff --git a/client/src/routes/profile/style.css b/client/src/routes/profile/style.css index 756d6bf..a7c1845 100644 --- a/client/src/routes/profile/style.css +++ b/client/src/routes/profile/style.css @@ -1,6 +1,5 @@ .profile { - padding: 56px 20px; - min-height: 100%; + padding: 5vh 5vw; width: 100%; } @@ -21,3 +20,12 @@ .links_container{ text-align: center; } + +form { + text-align: center; + margin-bottom: 2vh; +} + +fieldset { + border-radius: 3px; +} From 7d48bdf55ec9182704266466e68af201e8299521 Mon Sep 17 00:00:00 2001 From: John Kwening Date: Sat, 10 Mar 2018 13:27:20 -0500 Subject: [PATCH 31/31] refactore: Style reset-password page --- client/src/components/AccountForm/index.js | 28 +++++++++++++++------ client/src/components/AccountForm/style.css | 10 ++------ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/client/src/components/AccountForm/index.js b/client/src/components/AccountForm/index.js index 4384a69..a2ea864 100644 --- a/client/src/components/AccountForm/index.js +++ b/client/src/components/AccountForm/index.js @@ -110,16 +110,31 @@ export default class AccountForm extends Component { if(path === RESET_PATH){ form_header = "Reset Password"; - email_input =
Email: {user ? user.email : ''}
; - password_input =
Current password:
; - new_password_input =
New password:
; - confirm_password_input =
Confirm new password:
; - submit_button =
;; + name_input = +
+

To change user info:

+ + +
; + email_input = ""; + password_input = +
+

To change password:

+ + + +
; + submit_button = ; link2 = ""; } return (
- Navi logo + Navi logo
{form_message}
@@ -135,5 +150,4 @@ export default class AccountForm extends Component {
); } - // } } diff --git a/client/src/components/AccountForm/style.css b/client/src/components/AccountForm/style.css index 61e005b..c16a15b 100644 --- a/client/src/components/AccountForm/style.css +++ b/client/src/components/AccountForm/style.css @@ -1,10 +1,3 @@ - -.signOut a{ - padding: 5px; - font-weight: bold; - color: green; -} - .inherit { display: inherit; height: inherit; @@ -15,11 +8,12 @@ display: inherit; margin: auto; padding: 2vh; + width: 50%; } .form { display: grid; - padding: 5vh; + padding: 0 5vh; height: 70vh; align-content: flex-start; }