From 778371734f790e3f6da700d92518f9a307878b5c Mon Sep 17 00:00:00 2001 From: Quintin Date: Wed, 22 Apr 2026 11:00:14 -0700 Subject: [PATCH 1/9] Defer FWA index loading --- app/src/components/map/FwaNameSearch.jsx | 48 ++++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/app/src/components/map/FwaNameSearch.jsx b/app/src/components/map/FwaNameSearch.jsx index 63cf36e..c1ead05 100644 --- a/app/src/components/map/FwaNameSearch.jsx +++ b/app/src/components/map/FwaNameSearch.jsx @@ -1,5 +1,6 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useMap } from "react-leaflet"; +import PropTypes from "prop-types"; import L from "leaflet"; import "./FwaNameSearch.css"; @@ -126,6 +127,7 @@ export default function FwaNameSearch({ onPickedFeature, fwaStyles }) { const map = useMap(); const [q, setQ] = useState(""); const [busy, setBusy] = useState(false); + const [indexLoading, setIndexLoading] = useState(false); const [results, setResults] = useState([]); const [error, setError] = useState(""); const [index, setIndex] = useState(null); @@ -137,6 +139,7 @@ export default function FwaNameSearch({ onPickedFeature, fwaStyles }) { const abortRef = useRef(null); const activeKindRef = useRef(null); const containerRef = useRef(null); + const indexRequestRef = useRef(null); const SERVER_ERR = "The BC Geographic Warehouse Public webserver is unavailable right now. Please try again later."; @@ -150,9 +153,26 @@ export default function FwaNameSearch({ onPickedFeature, fwaStyles }) { clearUnderlay(); }; - useEffect(() => { - loadIndex().then(setIndex).catch(console.error); - }, []); + const ensureIndexLoaded = async () => { + if (index) return index; + if (!indexRequestRef.current) { + setIndexLoading(true); + indexRequestRef.current = loadIndex() + .then((data) => { + setIndex(data); + return data; + }) + .catch((e) => { + indexRequestRef.current = null; + console.error(e); + throw e; + }) + .finally(() => { + setIndexLoading(false); + }); + } + return indexRequestRef.current; + }; useEffect(() => { ensureUnderlayPane(map); @@ -344,15 +364,22 @@ export default function FwaNameSearch({ onPickedFeature, fwaStyles }) { placeholder="Search river or lake name…" value={q} onChange={(e) => { - setQ(e.target.value); + const nextValue = e.target.value; + setQ(nextValue); setError(""); - search(e.target.value); + ensureIndexLoaded() + .then(() => search(nextValue)) + .catch(() => {}); }} aria-autocomplete="list" aria-expanded={!!results.length} aria-controls="fwa-results" onFocus={() => { - if (q) search(q); // repopulate results when focusing back in + ensureIndexLoaded() + .then(() => { + if (q) search(q); // repopulate results when focusing back in + }) + .catch(() => {}); }} /> {q && ( @@ -370,7 +397,9 @@ export default function FwaNameSearch({ onPickedFeature, fwaStyles }) { × )} - {busy && } + {(busy || indexLoading) && ( + + )} {error && (
{error} @@ -454,3 +483,8 @@ export default function FwaNameSearch({ onPickedFeature, fwaStyles }) {
); } + +FwaNameSearch.propTypes = { + onPickedFeature: PropTypes.func, + fwaStyles: PropTypes.object, +}; From 03aed304e19845cc35add8942494d3c23675566c Mon Sep 17 00:00:00 2001 From: Quintin Date: Wed, 22 Apr 2026 11:16:28 -0700 Subject: [PATCH 2/9] Add preconnect and favicon --- app/index.html | 6 ++++-- app/public/favicon.ico | Bin 0 -> 1406 bytes 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 app/public/favicon.ico diff --git a/app/index.html b/app/index.html index 788ef3c..a5d40a8 100644 --- a/app/index.html +++ b/app/index.html @@ -3,7 +3,9 @@ - + + + Vector Hydrologic Model Output @@ -14,4 +16,4 @@ - \ No newline at end of file + diff --git a/app/public/favicon.ico b/app/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..523a7908716a7e0366ddb635550d2b2ebb84a1e5 GIT binary patch literal 1406 zcmeH{YfzMB6vuxoSXzqM#iA&cGEgI6v7!t$Lb)vqQW=UBWQLGHUVzmWM9^J~Or(&O zy=ICZ(sUx&xa=;OgQX5-j)>egy9`Z~ip?NR6df49`l&v4-ub=%bN=U?d1jt@=LHXW ze0-4iMAlA#=|G?$7Bhu0|35_KJWwmW zND@?G3e;hqsKaG1+#6N+RFXwgqx?`u`;!vuPxgxW=DLI;D zloc#zqc)N3;uP{Kvd~nl!%&{b=E@ujDsySrTR@#5pSl_icGDK>&4n~twAd|$G+8CL z7V(+2ShSdWYY9!ZA{uPP*o9`>HfA)hqG?|t+Ygoy=u9WTwVEJDCV{RD$_|yW^Kdyk zj+Wv4Xb;DaRPx2qDq_AWqUF>5oUmJ1d3ragU+>}@XRYut?Vlf_uI&h?kJ+g@b(l@( zOswyy;cVL{oN24${K*zNPqk3pQBP;P6YKeU%$#Kozz*MU{k*z3e3m<406%m~Il2i1KpOnpvj zM9qDzScDpPD_!T>F}sg(;9@gY_i=3BJLv2=iS@@5^t-=hz}-Rr51st_Q!l^uU*ycy zZmwLp#HFi0^ZVccgM*j(Zs-@>Lzi(64=_AD#K@o57##V7zelbyI{KF|dZW+wfB!$a zfm+3^2d{_!?0|Kp2XC6}b3JZ-{JD~?wR3##84F+EX`WB)DcETUyJfug_Vx>XeajC0 z+7;8s>nSt6GS}-g`sGG^?-b__zu;ZPTCINJzDK6qCiS$tpDovI*XmZ2BY7zWef;z3Jf(KO}# Date: Wed, 22 Apr 2026 11:21:35 -0700 Subject: [PATCH 3/9] Reduce log noise --- app/src/App.jsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/src/App.jsx b/app/src/App.jsx index 2b65941..98b628f 100644 --- a/app/src/App.jsx +++ b/app/src/App.jsx @@ -1,12 +1,5 @@ -import React from 'react'; import MapComponent from "./components/map/MapComponent.jsx"; -console.log("Rendering App..."); -const App = () => { - console.log("Rendering MapComponent from App..."); - return ; -}; - -console.log("Rendering MapComponent..."); +const App = () => ; export default App; From abe70e09ea8ff0dcef700b734adf7ca78530cb8b Mon Sep 17 00:00:00 2001 From: Quintin Date: Wed, 22 Apr 2026 11:22:12 -0700 Subject: [PATCH 4/9] Use window location origin for timeseries base URL --- app/src/services/timeseriesApi.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/services/timeseriesApi.js b/app/src/services/timeseriesApi.js index 0345707..9b32245 100644 --- a/app/src/services/timeseriesApi.js +++ b/app/src/services/timeseriesApi.js @@ -1,5 +1,4 @@ -// TODO: Update this URL with the live api -const BASE_URL = "https://beehive.pacificclimate.org/hydromosaic"; +const BASE_URL = `${window.location.origin}/hydromosaic`; const formatUnit = (unit) => { return unit From 6e547779bdaa05587ce5a880d410380a507ff214 Mon Sep 17 00:00:00 2001 From: Quintin Date: Wed, 22 Apr 2026 11:27:47 -0700 Subject: [PATCH 5/9] Convert logo to webp, set size and fetch priority --- app/src/assets/logo.png | Bin 10041 -> 0 bytes app/src/assets/logo.webp | Bin 0 -> 5644 bytes app/src/components/info/LogoBox.jsx | 13 ++++++++++--- 3 files changed, 10 insertions(+), 3 deletions(-) delete mode 100644 app/src/assets/logo.png create mode 100644 app/src/assets/logo.webp diff --git a/app/src/assets/logo.png b/app/src/assets/logo.png deleted file mode 100644 index f3107a7fb752975b55537eaa6a617277907df035..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10041 zcmV-9C&t)`P)TkBFWdkm*WX=q>&3hO z#DVvpzd{)MFI*=^Jre^GV01|WqHlk`B<^unw|Jhtcn{O>pVvRE-E?yfP}Z@y3n*JS zeK|xWTs@p2z{3S$JLqd5iyNjlK)8YRQ;_vC{r}GZMDuqZg$N~7Jk353JkNROk&`Oh zcI@)cJ~n5~eV{l{4G{d>J+Ch#60RBIVu%z(1j0sBaN+JF2zOmW4#awhGM2yp|1~Y% z)Vz2T#9|=XVYMJ<$sQo%!OJ&5Qe2n=NCK7Z?k)k6tZpel?(bcokT`hp=EIk7m|T0pZ8_0Gk?T&J`0*aiNQU{U!zJ0d5xG<0rR6i9c0<`$Wnu$Qg zKs7)qAcB|!E1Q7|9}9`eF( zEA?f?_=S%_WPuT{AR!W9Z8%}=Zcv2nnTMQ0(L|te4;F#PIy7-02}08vkOQx1jyKb;RYl@0TEE@+>8bwcV1~S zToCHM-+%wYlTYeCPl&}pa@xXW5EUDzT0#5`B;(wy7wtOgZ)Ldg*m-ygf&d^_CAI>X z$}k0i>GActNx*am7YC+CP$GpZg;+e@ej5WS`1<`1oc;duHz3)W77j^$z_hcovjj*& zxU-59fXND&xFCvw;y}ZJNe{^8;p9X%^C36~0R#{tzOjPD?zszg9)(90u*`w5%Z;U*iC1&hJXqFa=BJ(lDP(}D2ciX@8XmlOqZm^LHwuySISN!NjkHy7?Y3N##U3oy+9oyUUd zRpf*TvcPZ^Gzj*%&v)4gEN6l2)7M%4{5Upk@f~2Q0Hy~g3o#&q>jD}Lbiw-#Qy{(q zS_Ul5HXJ>NnH#WLjj0B|uKA_OXqgG#%?9?ub&TGcD|i%yeX5 zNq?$+`u+=?Ya}m@8F;`FuWi;1aOv_7PJ+s$ZL^@k@%JB)4YcUkZRB98Ien`y-%pRh^sGdS)B`b4b(XM^>etDd|tefFem&AYEl^0c6^!8i8eK{N6$& z3Ti%~;=g#iaCmR|?KTT#sL+VaR-$Z6bHbS6;-l^s7zn(iZxeLkrw;ViY3 z@$7S5EjmC~m`)|VMT9n|taT)!dQqLgXI*D+VdYKPogt{DlAx|iOGmOZ7o|5z*B-yr zHgX&}8M~6Ws_849jMckW+LHbc-ey{Fq2h$i0kvDQ!7qER&fhVYFZe01Z`=!_-0Wf`K3)2B7HdN7jyKy_$p zLb^A$w^uxRC0%5>mff;Al^RFxl|DV&hC7VHg@G7xc5x1QfYYf}g*d1qnt`X+r}&JtJsVsuN`frof=9(yK>XMr-fDpRcX!5d?;^=2Ul{ zsyTP>x!QGkD=pi8@O0?yhaZM(T@yOY-LjEc5dC8ot0g=~tBhZCncapVj-tKmD_)*p zhncDrfo*AiuETwT1s0Cr^U$b_A}&iS%UsL!{pGb>Mw~6@n7Ri?a#-!wW(DMW$9R~Z zPR{~|*61smIc!7Ge)%*?)_49($dl^3UZ6!>yc|Uf`TIl&W{~kV`ih}hUvQR!c?%3v zCRS!F zx-WkD?(!v)G@*;zLqH2uD7GYbw?ek~7&_DcoV_b7fvQ^DTFs&oYoG9kYlm{ruqwCb zR$+X^ij{-EP5eBi`n|bVrQT|P2kE-l>c5ItP6&as!=JLbm>MF~Y`I|)5am|{G#p%e z!RaV@fXq{c!_{48T+n^TSXKImr`?zuxtcuEN?{P}E$lg?xasA)$|xeu&WzxqEYcLo z2A3Q%06aL=4=1*!-J!KOqOosy_H_G?C%+n1sgPAW0@d3Bd@l8!O)0(EeEkm~nz?_I zTy1RRIv2Br^(-PT1iEZ-FKj^q+wNvA0%@l!#jYzVxIkJG;`#p$HqJMV7@TU9G|>>x zZt_JFzquFb`3oo8#U&1nYaDMUK2+9KW;AxD4@{M4TT3LZxTrIN4Elz4ef@W=a+$kZ zL43p#$IG*Ad=!lJTw#dEGB;;FpF^7Cz+l%Vzu!@Y42xc36I3byV0EU}>L`G{La|ef z^_T4GW{J^0V9=$oEv$>MfmR0R8w!Is@&>W2Q}r|iX2jpGnKH2D1GR}K+iGK9PArMi z<#)&&P)e2hB#@NkYul5=z%ifvR&F$e6u)10EyL2v*C&K-zCS&=#3^S}sZu`b0^U-) zZOMVziJwUYl?3O%Eoa#OP0y#9P{8gSZ#s#>#)LzFibcBP!hbJb*Y*0%5wRvpCm>39Qe_fuP^@#O+Uw(op{7`D3DL^4_(w&hpdNldIkH;jF zT8S~d!g(k;PXE|HBIl&^f@8#(PuOm^P8m|TV5%gQM_sPCVfkrjOj7?gke-^1)+gH zOTlzLurYT@C6%!nUb_#9MB7HrK-66zegAU#yVqZ99s1m9>+4VNOWS<(gL7?8TXS}X zM$5RlQ@lU>X2{`%76J`Iyn^1FIqqh|8YLH2a+32+3DIG6y%(g$qY`4B#knL;(TTgjgs_{??83PT37R?v4Af)%lgypBciLpotOhuW^moG>v(NXvxEAbGJrZR!8 z(!6u{hNV{thM7y{Y3)0dTBCe+MXrngu<@pn0Q9?1&ZqjXhl*-%a|c`KD+x`JJ@~C{ zF%OIXVzZ_IwJ%zc_eF;--JY`E+jC-irojdtJ|PyU_N8*oRWmXLuK2JMGS1eo)yHB( zg_|HG{bMGBT$ZJ!?z+;3FU;L{M#jm8qjg{6(|dO&tuiSL*x&<8a6p;zl;c%oJg`Jx z!T`O{7aCB8Hk$9tff{PX(#b8HldZ{KQwdC^j#TOA<%ua^R|(<3toi%tKLOae`k<ijtDd*QiuPO`&1d?RW2a@33$0-piBhk7nArqxbDSyXWjVd(Q5jbC&bt zR8hKFjyC>CZpPu4Mbn8wKV&x_!Xb^q3^(^p>eV^&^qI3B@Apv=U88z*^*bkhQJa5A z19*y!8%$!mk%@LokR+Wi%KxQueuRw!!wcm#G*mvDQMSO=`VG~`-VlLjTsiOBUSqb@ ze(v%9&@;UAQ{zXro;fomyHIQ{h3>4}AXZ0YPMNUsjscexdJ?09+?(02*IZFZ*>Cn< zCS`9l8wfA?C**VyWe$nIa2gFei!QJ@-H3w~T~eX{M8J=)-zLTsY3FiaLr!?NKi3>u ztovAm^ViUb*ag?-?)apB>-)#HI(FgMy*53;`%At18{Nw``HqYFMn#Vq*$0;VhPWPP zrwT`d*?%NSmwb(q|A#`v0}KbU)hXHPtC*wY@MqzeCC&LkG<-8akOjExy+BM12qQ=` zA!NX;#zHW|2S=ZS2aOB*#oRP|)5uv^(XeIlXKB(W67!bYItmPA0l@;KTsSEqL1$A)gi1d& zFAy~0B%ZLfP>w}R83+lUnw*kKO4XGljk$wyPD;ISdd;}XhEl23+W4~D`(#1P`;Hv< z)ubnM4R3t+s}d_joZ)5WEGrO?pB0+8Fg@4Dajx%JVWwkrHp8hokHn>)Z$V zS$HIXNq)ls6bFtRvtm(!-+IIN*`rg|i$NEzFA!D)YC?L9*(~lzAb1;GO6;Kyi<6g_ zk|z5}+{JrNR4>_;ua1E614C1+^A*48sms4N6zj~$s}oz^UWjxfT1*m-hB z8&L~`oSi-?BWctthNnyn*-;9cLfV=tROHWP8{=BZ=oJ0XWKBt2UGBC)7a~Mv7o{gF zX()EhXfs8DvZAqwebQicscWWLV;T!%*Ax1*wk#@*Gr(*l{inOAs4lOlPA%!8u{+I@ zMoGDDNRKI&JEnnAVJgk``AWr~^w9mN{Ts5mrfm=LTT9XW`ynTDZ&vT(BUWOyrT|*N z)NK4gYLfrR-Jrytcq_c-_ku_6mOkBY*!IknM8-I2)HQxfR$(<3B|qCTEqUeZmGYRC zRL)ixZT=#E&k6PM;Q5s%%x+6zZa|+KX>h)i_Z1JCpdId_lx3#4I zs4jw-tt35hptEPE$jmZD;A?PX#1-kTbEQoCUpVJo*dkYLB>lx?{KfEDzB zDu%?%v+2pSoQoOGR4L^=b3vcal~$oSfe{&~Es_$@oi_kX4QG7CuH;)mF zBS{1D*4UWQ#=~v#XhvGL&S+=yfXJTGb_Oi+$<=6un$(=NRD+oTzEd(c(Ms>Ug?gdf z4azaY=1fUUPaH+Wph0LC3U_0uW`5K#X^sCG# zq*9$be{NtlxmYF)NJA&Pzw}zEXH|P=(3y+&o0o0P+N9%<^FaP)^H1mjaV7LMRhzX=#YV)CvH+rTxB$uk&pA$Cv{#djB` z=}7@eSUH5d{h{2n=~3uUG`Ds{K@gl-kA_ei$*S3q-DYqlN$;ot!`b zk*RZSjFVz9((OaLcfmf`gU- z0@zo$h$iU8Q!@#S z2n)EAW)uSJFRUX2L=u}RZ2MCwKCn~a2onfaSJdjc@J2aWO>lx6#(S$j{qZG<#_ zK-#jm_F8?7=+bF-aA_(Zd45X1t*;pGQhGk{FHw(wHIo_Nxx%&3nT((FH*Tk&czko* zT}$tW8oc8cwQ;-ILP8PIw(rzT;+JIbTi)3OZTqF=6q+x4?M>XPc*69yqtT)|HB4GJ#DNb_%SXkkC5UQS}`$bi00^oDw!BEB%s8~jN^wh;YRwC zBGU{5w(;={5t1e%B*^f83((%RKvh+x;oHO-K`#hk52!Jy9~Uv$P7};BhQ>yO(lHA8#wGu5p90df$pRw4vHt*o*+V66 z-UKX(GbtWop_3{GZu47v??eupL1n`pw8}eJ27gmh*|y0Pw0hnwMcfq&kjgGJ?<=cR z#O}@sK|~*&uqoop0tM9~@V^RrQ2CB*D zQZlb#5t0x{Y(;B%WovnTN9k!p>07Oaw@MV6KzdF7v!{$SUGt-RwdI={OKWvatH=(u zxV*hQ?hU?aX2?YRZtFfMdOoWgvr4x<7)c5)9`s2$Q$E1^%WQB+Lmhk0ac z?8&a-S!frD|9F)I8xuz9_H@=~%-a3K#Y1Nb&1W_qE=hOT3YK|p;FEB(;Zgs+rfKuL zkR_=FzhT&*C#DC(N<*H@TK05b?s68FNg>1NADt)Wz=cpuRj-_p+$3IMk+KK8WApJIa3yF8wt!;-ew7dbIv8S%o4iKfo|b@{ zYx9dPaEIz3%q)k4+?s7qP3T8x*UFY{+K1ow$xdGaFPC+S{E%koH8;B|L^`+!{#qb)M}DQU;gpGhffuDe&1f#_@C_jM)|fmO!2c%jO$my zJ}z;y!6KMonofSH3|=8`Q^Hkw!VdO0T87B21Ut_DGbx?@3Xgu1(7y%L7T1XtoUfG2 zev0O2uJ(IJROVGAX(&u_cA=RU4XAZRm&CO~8K--H+K#pNNw6t9kyA4PAb>F0=Y382 z*(C+~+Xf68vut7p1iR(mU6K$Jx#PWJ<|I8Ycxdt5+;T~$gRQ5mQC}Sa9)8sg`Bw|; zLd`ovg1}E$n@HAp(E9zz8P2Y;m&TbS79J?fGKRVqqP!$7Qep!kPTIj%SFV6F`7`;v zkUNYcqxXOO9kpl+T8Q;Mt5%PrAx23nxZ*DCc7ZkTO383mvqG42Q-pN;XSz-%eQ-Yo z;_ECCenPw${t-{3A9cVhrinNE4t>9>p3e5`DR1mP6*I$+t)d+itAqVowWoQ9%6Ki4 zoBHUDwtZ)^RB`sltYIIT3Nn_&neYg{I?ox`L?+zmJA84R3BnJZO?z@xCoN0kOxjRc ztxlsO>0z+vKtL7tq+MVqnX*TsBIZX$kPU%^oI2kw=q6t+FMXCVZ10+69&ySOi5`~B zHi>(g<9aqebzrCKKEu~4tqIh?qH(gr?ie>@bb#Uz>?XgwvI_$dOM3o(UVniNrokhN ziqHk8{Y^Olih#LUojI6I$-tad1VD1NXcNqq!kwSwIMp`7&y>(B(qCv-9_Hn~{N70( zzjcF&%ie3&KT2I=C$70O{pZ~4uTQS6&OSX{eLR74wl_XCXF-%vPN?+!-a~*8S215- z!m9Z(xSn}sCyx}K%EPFJczG;{if{^MjmQzTJEMHP+Y2`XBgg=<2NbJGwTRD;%bRhLv7y3NvVCWz;BlP4>|v)$$^V+g8ib12$zfrw0cu zQ8GSIf7MMEUQ{5xAUpL5o+h@&ogIhD@s~#vbtpNSHdKSXJS30Q-g`MrHpD{U05H`3 z;hN*sCoB|wNBj+V;G*l?rUF5TCcvvmJlepHY#YSb&5*JFA-3>oJ&BO0jt0K?M=|Ce zM8>!bkzDR&p5nM<>R4B~N-zIF0XQaDZ1Xoa?Jc1R)juz4Fw2WHoKHcdQ!}fb7wH8; zXpVs4{^kN)&NfdC%?J`-cW)}G_^QM4))b`r=}1AUC#ommbntpsDWp*Oo!qb4HGeHX z`=XV1`q8Z19nL%6P)?0IHsEi4M@?2`nzPLz&ncmTckzC`rSP)`Jx$(L)C&tR4) zTmvhV5EUb@r_L`^u$7kHEJ?1j<+=En=fu|r>BkmXE;c#a{K2t_k^ZsW-(TKRTETxQ zPrD@F9R@5m6`K2!xh6aRg!aiZ{(S`_8YK>94z^hgwu2if`Bn~PMrJ>K?q4i<^~k3Z zR(-=K<~8nhQsyr|ZF3hPW{o>uls93Sm*oZZHPR9DfXUIJ0%TbjsfwUlOlg^lFIj;I zWqHO^)FIK*Mj0@$h$7ZpLTv&`txv|B1~KxDj|b%o)QUMHl{5=Kzlt?K-L{$sOoNR4 zGy#kT6R+YAi<)b+zDBJqK>TbWdoJ!Jh;`Osb(!320JF|#b(SW=nYC%~TP z-se3%+myv6Gtlr{D9V`qL@TtFpez~pb(o9Q8PV%KZQ8W#VzV|P7L8?K%bGtVM_zZuiF~B=AR`i?n4n1iCSN;07m zS5w{_-JyVPM&zmEg9urgONa`S7Tn>pN<6?hT=Ps3pKM)?*|Ex#VOdp&X4jwMdv|U& z7n;GlkBM0vG%i5MOEq{SIo70DjaM0zf&$k&tCDz~g=&gBI?x>^F|URM^5ob^rozx1 zEDcGnI$>dh@;VV?(S3~0tDclscS;8B6r&6=BYgAd@KBv()Shld=8@NActO8l7CO4R zNg2u6sWvx7X3sIu zq@=Y%#tltm0fT&&`IQBFV3GIH#!!$Yc+3qt$*4WuYLz8F<4xfVDa=CDvP?C0>ao~6 z4we5tEz1Q-fK(sYkRs^yqYE1@)VLzmlk(iJ^*mVHe5me}v&|vcqNCBSku1X5QvCke z^*P6Vh7DNx^5<%j-K$)!4wUY7o&)KlB!bEpKI_u+k&f#;9awA_XZpSgUGb4d!t@E- z$`D<7-19gtJO3pui@IXp0YO<;Pz*bxE!i5ThAzN!_HWsIx2do0QtNHy!!d(71Sc&@ z7rq!TtCkcS$pZ=O7&r3p#79P0?cG*1Ji9x46nDHw4ml`%bjvFC;TX~aFuCZ>VCU7B z+uYUmb>f#PVR$N(UF4^nL~yzp6a`*-JE=wZdgE$(ifpEjR!L8?*wh71x@ zz_c0qwP3yd#-8Sw8Gi80*DbwGa@y3{H8zMIZ!#8`%WX>6i0dQ!^^U{OHByl27HzYm;`3&&&o|E45HP2ffSuSU=BU@Kdav4b;8OZGy zc`p_psbtOB(|eX>eWbLUoEjW7Rb2D}Hc*Tx10dzh4+084wrqYe=z)xsaN8_ULzb;Z z&kXX9Kmq6)0t0^s+JDvCAm#v)ueSjM)GLD-BzpCkh4O)}x%mC%^=}uuCICsXcZ2AS z7it?jYg}l4^Wfl{hm03qGq@zxD8IYu`k|igAj;b%$zQ1eUgo zp1ymevbMQ}cxZ^H$CUAbP&cf9MPMY&Kdx=Ka7oyULeKY24w)M4L`H|=BUQCc7DlM4 z;{(T!_Kyyqz^jkq@~V&P8VEwgAsG5X79{&eTlbZ8im(yUB)#Fzl-mOp#Shc>?$K(} ziBv7xIDyx9it`I}wiT5E47$lT(U?JvM?ej;Ltw~fhi}VpXVj207~T9oLrTRn6vjai P00000NkvXXu0mjfc4R(Q diff --git a/app/src/assets/logo.webp b/app/src/assets/logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..0c12d27178ed8b69b0e3bfdfb6f09f36dd524033 GIT binary patch literal 5644 zcmV+n7W3&+Nk&El761TOMM6+kP&gp?6#xJbPXL_(Do6n)06tM5j6|cNAr{(Z;5Y>Y zwg6%fylBq`KO^Q@Tz@nDoAy7kZfSal%2$~GMf+j@Q|b%!zpzL64@|y=yutaK|Azg# z_euR{)L;Ck{BKzwR6p>(svo)DoPN!J-9PjCM&_vhHthrYcjGthpRj+6{M+@9$RFMx zR&OM|N&dglPvd`GKF9rs_DlOO?bpYD*?%Ry75KybH>elmpUMBZ{!;&S{kHTo?$Fe~ z)A|8=r}OXgpWy$$f5`tE=@I(>JbkA|Y0E*IHvorFD)h6Lsa?mEiB;Bi9i*Er z%5nx-FmC@ee!w>{&J%T)|4F1DX$jw2z2y?`_MQD2_)J0uj7rex$P8^DUEZ=GQawNv zvwLSq%Sg2De80LMnzcMD#D*% z_YX66un^{CPwnU*#~+q~Lv&|-|KEguhqF$FP<2Yp8UcKt#N4Htymi1^Yd&ivOcL{S zV;{7=aI8MZKwUQAZ(Vl~@rXjmZ!=j$_3)V`GF8B1Pf9}Omv3*3Q#jK=X&6AtB^ehB zr-kw?!~EB#B4+~?__0@(^U78Nb)1@LsErJOB_0RH~ncsq%o z?`9CHV)`o~syeMz;_|vM6VhJWtRFnFv12vDjd7ezMnAzM>r*^-eK`079ipl*5~v`r z?JattvdY=Ri&yt7UV8}={WAR(*n-TMUDBb3a=u^~)Pm4KS{aL#>9GQKg5c0c#mr7u zx*+P>7d@3%LuvtSFxfD&gLl_*F1HC@802x}zym0}c_lQc^W21Rdn;Z1nXA953}-A1 z!@%Utb(S$`&@A=v&P6rSK5I**y^pP5$EGH+^AKuj;7@b+)(vwHT(}$qh`{V;9&yb9 ziW)@;Ms4lgO=m7(>6_t@#QiZx8L91&rZxc70lD>as+D#Y*u~cjq6YOZAi_gzX#ZO_ zulw0``8opmK$?R1^3GAH>(BX@kkh4)*Ty_oHs6Tty+ z3*4G6XZF`_Cfq`{D5i`+kgm=8#>Wp7<~?N|e;r)rhum@%n@;(?H*$x|V$`lQWV7bm z3rnt@%Fd&(e~56wMSq4OfU1DDF3Yt1`0zxSzY+r3zF-J05p zzDt6G0=(f0c6Go_{9pDoZ%0}{UA;rK^0+a1dOtlMM+Dae0Pb*a$gxkD<--q-a!s~3 zrY9haHV z25Tt0-q9IYX*F=!>N~v5fCCsG>BY%*^Ff!h&A2)okBzwmjt5EhE&gqrUBL#8t*M#; z;31}g%W1l$c`*W0I2bEx>Ib-=3(?rF=y z5(j%_Q=linl|uHQd&n^?6^q{>+0DGnv`G!=^y$HTE7CQQdu>m8DN^4@<^2X=>N13n z@ASexT9MWpfkxf%A1Pu;OOQcru_GEjRcVIEh6?J!WAWa%O>rby80bWdtj9L)dSn~$ zU05E&WZXl_f@cpXKmw=ikf?OcNcxA(|2yNv z{jkWtA`^Zv+w#P`{%p&xe-nF`@vHV$GJhFpFXt%ZsaUTfC2F-o@zU;#i*YGohOPEf zirOZttvOX_K0Gy^5X=mY_R~IXOga&0xjECKX@d>)IV&NY_M7w;4Nf{yCo7UEFyJ`hd*xG74rz|9hWUK649e8K zHnOq0E8=~~2O4KGi2DtjrgbzLxW3y4;s@zjNIv>T3?_#VB5PYn(s?G8jHCGL2*wNG z*dG=k>)DOs}Olu}qpp*6|OPG;0bzdFnI;k|{d^6WGFVGlfRH=qfoWnvaGHzfD`cA~$p zV$326*;a>ap@Je2&qcEfF6~9IX~kJA+`A=EnJJdXe0nwDdUTANE1Q9S11kX~%`Q@v zSaRv2nD5se>DCU_*%i5_(}ev|^Tnw9cbI$hzq7YxV%MGEA*8zWXV6O({2oE($>YoDbU_e`xVH zC%(sBFhMidbnea@yaRqo4xd6S2b`IDb%GT*=3JA@2> z?Pq0M4B0|x;*6|iZBr;VkYWAh&p@iS_4SgoAFA=9q;ckOJ=jd0(rNN@(cL7lr?%Wf z=5Oi?f;lC&6<@9?YK!Rx)(*Le>oZ;plyS$GQ3Q4gT|u*X#@WcaMBWIzm0<321qGAZ z4G*hfemEg_V_X|-$(MP17K{4{w!mzHI^SJTH7^>SpcO+1D1U2X(#v#rDnAad8%cdZ z+HRA|rjl9(VEl=JAZeR7Cl2E1G8ZQn?h;J6Ne>|&L$s9S$mpMQU1kikA)Zh2Pxp8R zj;?Mvkta$fU`$QlKo)1A?bRskj|Ac~0=csv`eNt+psPut=TkN2Z!ZfmitI#EG_SuJ zu|j^0qPsBDQxcVnD_~qxM6hj&d=Ky6bCXtOTBbE)c;zGs20$E2_L^B(Uc+EESeX#c z4tgl!$_L*+dc>wtCY0WE-LTN{XycpB_vBV@hmV(bw<) z`{qnS#9#S^%LuKm%{f{4)n&rQiSr2h&oP9}eLd?6SF}+#oMRDs9(IZ@!e+j9dq~fz z@b)J#n*_Z=h=lGTWL9;lrL9u5sifyCva(VwvNoM&v54OU`zTe;Z56E(v$qTRp*IKp z_#~h`98{Iw{VJSbbXjn}HYaGRv_~I5A~&>s4^wDE_^9PLlrOF`oyHXxsCG{n^oVW@ zQap$FrI{I1+f}=N(neMS|E8~Cj|4fekZ)oj3|`(TfqYO57;)WJ%Ru%NGcLyK%?@%8 z7QXS=9YH^~4|6$mmaR4$K0DO&x{sEYHoX=?sjzRi=Sx|M)gJ|bUFV-Y7D#ZysbktX zlMS3PjD?)U0VVkpD0s6@$9?ZgjlNQ5l|2Skj_o0B(jx-+Ff|I6*MId^q0lwdd-{EM zj4z)8kJlH6vw#}#jeF`@;{|I~OF<1G@9B2dDuVglpR|)$^nM(5=4_%xjC`hZ9CP7@2)g~h?URR|- zg(&2n`ICPKW7}#E!gdBQ8XmMG=2UVcL0GWsT0QpJgT{FR+ZQgV`Wun>qHd3Da#FJx z+w@`R!$oUax2He;P&P^B?DSgnuSr22Kfq85zAhbfg32=y8(3I77K0h63muJNnIFui zun@Bw#RRpBTa`0s^K3U8zl|9QRrl5A$8Nu_N`PaZUc$VI-*YDAwm94`o%lx^^sUng zS99_-{4%M0^i!};0dRNjvTGY95t|C#`rrq22k~#zUoo{Ts-;Lr3n4a?*K*#!p6d{q z?zjX;_O!xhyBtcCq4|572k}^PZ~6Z;nddJ^PI+E#OURc0{EX?~l#tCpcCr!eG>}O8 za5DR`6?7CtW<3J8`^Z%0>0REf7hp3#Yav5AkTRaXUD0|<3j*L1Mx}t|C}IpI!=g7I zS$G3O_!{2st{;Lqt9j+6g7Y+`eWgFWiIaU7bUmFpYi<)h2cCvBttFWd@iKGGJ#9|?_`L$A+Ht+Q)l3;|5xodZV0G98X;AJgR882G;*zc00!e`Xti)z^*oPNtBTeiLOkSsJboIW4 z3ak<%04xPjAeb&ISl+xHt8Twd)%wB{1%~Kc%+R(1zD;~A0EKs*SGUH@1uJQEWbz!U z2rNVYjzROV@HYava=gIcuMXY*x7@ndwFr%Gp>RG0wkpVOqS?>YThIETWS~utZz$LV zYs}{?4~jUBb9nQ;uqRg|Qg~qRuD~H^yjQ9Ov-)NT@FNQx>*iyoVJ@Mlr?3CL4H1Bb z(L8ZL!9FUU2v53dfJ}4y79V$XUux_*u55rQ1K_Q@Aq{*lh!^(wO@xcSozm{2Kh|^D z4rvXqW;$DMJ^m6qfl`gBh3?V0pdfqxWUhlJAa0mRoJB*z)16<5@6yYI6#I|_b=Pd% zD?&Bjsg++WutK^^E9o7#HNkY|E6$=CyO)l^ zG~tirDq_f4htk7s=kBrR5-8p%52{^H*mTq%4ZyD)0w*9tTu`pEZqktN?F{-ro^&X$ zKVEToa6W`4LwIo$U$XO`n@b?&1^^{(`F&E}{$E{2+u8+Zg7s`f<{P$0uF9puYgv{> zp~aJ?G}X9JMF`F|WtcfbuBtj-Hlk&%Tl=nc+$uG!9>BVZy6P6^gODM>vMoZ+9*T4$o#Q$Bufy_j)L zXKdEnG^ID>j$jb#8`;UF%gM=(nRflezYK_*(BtqSjbyOfuuBSWr@_Wr0{#;L@;r*_ ztnn=58%157EOqRy^Dr;}2ax6lY_aO`FxEE3>3qQ$R(3xl?dd?q_&6%?htRr(&GRDK zsFlK*(C%Y5^nG2V@Z@_F959cN9L95O6kuh3aNvNy1Qx~^SZ9SaAIx*Q$LRirh|%Zm zaQKpC04Rn4Eq4YHqIpbrH|c)U)*M4FnEXVJv6=Ggs(Ezr(JD#- z$g&Uge6&wCZ0y}B&axq7AlP8>Na)$OCt@Up#B@9Rf3Os>8UTPCyZlloQ}vT;qL4O| z%QH6k?R5Og`M$|ud$Ea(Bid9vDxll{?O*T-%l+tHCml8Y>1TT@H$721dEZ3uws&pQ z{Kxs7Y4Ud;eKl9InAh*&wGiQJgig&&r(^B*c_q-b7&ndj=)}!DWs0(+b`?HrtX%F|Ez;{y6=xq9{?;s~bjJ|Ne>@aq@E_;6d`W8_{E-cX{(b#cQfouyfmZhd z_??>vMC1n=h6-P`qG1Z(MPw}@>WIeO9|moTE3(kkdzXKj6oEr?3AsVlAAJJPyC+6hY#GRP;hwiC|?CplwEZg={j9>O;k4%?^+4ki*JJ2fsM76!e;^>8PL9wc9UKltsqZ@%4!x07c5$OYFpQta977 zeyUUiU(^wc1P3v=`Fzqu}c%s8mlT zhr-w+oZVlPQ9sIZaoXba#G+ri2j(gfX^S2QGA#-y3Iu$t#Ob+_sFXy7DG3uuu>co}vx*o$^)zaK17-1X<=Di_Tc=imHY0aIlAr zQA8D)0@~9OE>?eWBBQNXa*dZ6p7>zAH{RFEkL)v_sTryKEFq3bn!r7y92bl?50{45 zgWNs1r9@TF_*ghT8Rz_IS9yhwl|{__GoOXebDr|hiindQJ#9x-BuaHHc@yN{q(=+g+X zUrd2MF5KBij#y00Kbb&c&qqdYoVzY({VoEFsvxA4K*Bk6$&4XBLV`07#aakpjO?o; zvDqYOEl3OThXvpCsV?o~2Kj<6bZ)x&;1J-pb6p!4Ojf_QP^+SXQA&lFd}gCE!#4a_ zIuwH@(i?TT?7Tk5hS(PZEU;lJ4{m4hBh8zfr?`=dFKK^gE%z@I#jDntu)5KqgQ9%( zR>9?NXS$~fs0G@${SPm70-S&a zv)yCb(}^Vbfx%$2^6t4Ro0FxjdhlDFW9q;O-cgIZd?zvMfgL{@&7!j5oJ`^R>Q8&R z<5n#tiR#>wYE5CEvgmu;D%%*(T2% mPGBZi`Sxez#4H@ER@!M21Qb-Yv6Nj!AqJaOtQbY;0000AZXvw@ literal 0 HcmV?d00001 diff --git a/app/src/components/info/LogoBox.jsx b/app/src/components/info/LogoBox.jsx index aea03cd..c0bbfd5 100644 --- a/app/src/components/info/LogoBox.jsx +++ b/app/src/components/info/LogoBox.jsx @@ -1,5 +1,5 @@ import PropTypes from "prop-types"; -import logo from "../../assets/logo.png"; +import logo from "../../assets/logo.webp"; import "./LogoBox.css"; const LogoBox = ({ projectName }) => { @@ -10,7 +10,14 @@ const LogoBox = ({ projectName }) => { return (
- PCIC Logo + PCIC Logo

{firstLine}
{secondLine} @@ -24,4 +31,4 @@ LogoBox.propTypes = { projectName: PropTypes.string.isRequired, }; -export default LogoBox; \ No newline at end of file +export default LogoBox; From 3473a7e455f755b388ee5b2724a6ce87f5f75af3 Mon Sep 17 00:00:00 2001 From: Quintin Date: Wed, 22 Apr 2026 11:30:03 -0700 Subject: [PATCH 6/9] Lazy load DataSelectionTable, PointPlotter and HelpGuide --- app/src/components/map/InteractionLayer.jsx | 15 +++++++++------ app/src/components/map/MapComponent.jsx | 15 ++++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/app/src/components/map/InteractionLayer.jsx b/app/src/components/map/InteractionLayer.jsx index b9c37a0..d8d1964 100644 --- a/app/src/components/map/InteractionLayer.jsx +++ b/app/src/components/map/InteractionLayer.jsx @@ -1,11 +1,12 @@ import { useMapEvents } from "react-leaflet"; -import { useState, useRef, useCallback, useEffect, memo } from "react"; +import { useState, useRef, useCallback, useEffect, memo, lazy, Suspense } from "react"; import PropTypes from "prop-types"; import L from "leaflet"; import "leaflet.vectorgrid"; -import DataSelectionTable from "../data/DataSelectionTable.jsx"; import { fetchDownstreams, fetchUpstreams } from "../../services/streamNetApi.js"; +const DataSelectionTable = lazy(() => import("../data/DataSelectionTable.jsx")); + const InteractionLayer = ({ baseStyles, interactionStyles }) => { const stateRef = useRef({ hoverHighlight: null, @@ -300,10 +301,12 @@ const InteractionLayer = ({ baseStyles, interactionStyles }) => { <> {null} {showDataTable && selectedSubId && ( - + + + )} ); diff --git a/app/src/components/map/MapComponent.jsx b/app/src/components/map/MapComponent.jsx index 79123dd..bead966 100644 --- a/app/src/components/map/MapComponent.jsx +++ b/app/src/components/map/MapComponent.jsx @@ -1,12 +1,13 @@ import { BCBaseMap } from "pcic-react-leaflet-components"; -import { useRef, useEffect } from "react"; +import { useRef, useEffect, lazy, Suspense } from "react"; import InteractionLayer from "./InteractionLayer.jsx"; -import PointPlotter from "./PointPlotter.jsx"; import LogoBox from "../info/LogoBox.jsx"; -import HelpGuide from "../info/HelpGuide.jsx"; import FwaNameSearch from "./FwaNameSearch.jsx"; import { baseStyles, interactionStyles, fwaStyles } from "../../styles.js"; +const PointPlotter = lazy(() => import("./PointPlotter.jsx")); +const HelpGuide = lazy(() => import("../info/HelpGuide.jsx")); + const MapComponent = () => { const mapRef = useRef(null); @@ -66,12 +67,16 @@ const MapComponent = () => { markerZoomAnimation={true} > - + + + - + + + ); From 43a883c3e4666de2d68e5147886422e4bced4ab2 Mon Sep 17 00:00:00 2001 From: Quintin Date: Wed, 22 Apr 2026 11:43:39 -0700 Subject: [PATCH 7/9] Replace http-server with node static server --- docker/app/Dockerfile | 5 +-- docker/app/server.js | 96 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 docker/app/server.js diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile index 3f62882..e4e6e30 100644 --- a/docker/app/Dockerfile +++ b/docker/app/Dockerfile @@ -14,10 +14,9 @@ FROM node:22-alpine WORKDIR /app -RUN npm install -g http-server - COPY --from=builder /app/dist /app/dist +COPY ./docker/app/server.js /app/server.js EXPOSE 8080 -CMD ["http-server", "dist", "-p", "8080"] \ No newline at end of file +CMD ["node", "server.js"] diff --git a/docker/app/server.js b/docker/app/server.js new file mode 100644 index 0000000..ee0f306 --- /dev/null +++ b/docker/app/server.js @@ -0,0 +1,96 @@ +const http = require("node:http"); +const fs = require("node:fs"); +const path = require("node:path"); + +const PORT = Number(process.env.PORT || 8080); +const DIST_DIR = path.join(__dirname, "dist"); +const BASE_PATH = "/vec-hydro-portal"; + +const MIME_TYPES = { + ".css": "text/css; charset=utf-8", + ".html": "text/html; charset=utf-8", + ".ico": "image/x-icon", + ".js": "text/javascript; charset=utf-8", + ".json": "application/json; charset=utf-8", + ".map": "application/json; charset=utf-8", + ".png": "image/png", + ".svg": "image/svg+xml; charset=utf-8", + ".txt": "text/plain; charset=utf-8", + ".webp": "image/webp", +}; + +const IMMUTABLE_ASSET_RE = /\/assets\/.+-[A-Za-z0-9_-]{8,}\.[^.]+$/; + +const getContentType = (filepath) => + MIME_TYPES[path.extname(filepath).toLowerCase()] || + "application/octet-stream"; + +const getCacheControl = (requestPath) => { + if (IMMUTABLE_ASSET_RE.test(requestPath)) { + return "public, max-age=31536000, immutable"; + } + + if (requestPath.endsWith(".html") || requestPath === "/" || requestPath === "") { + return "no-cache"; + } + + return "public, max-age=3600"; +}; + +const normalizePath = (requestPath) => { + if (requestPath === BASE_PATH || requestPath === `${BASE_PATH}/`) { + return "/"; + } + + if (requestPath.startsWith(`${BASE_PATH}/`)) { + return requestPath.slice(BASE_PATH.length); + } + + return requestPath; +}; + +const sendFile = (res, filepath, requestPath) => { + fs.readFile(filepath, (err, data) => { + if (err) { + res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" }); + res.end("Not Found"); + return; + } + + res.writeHead(200, { + "Content-Type": getContentType(filepath), + "Cache-Control": getCacheControl(requestPath), + }); + res.end(data); + }); +}; + +http + .createServer((req, res) => { + if (!req.url) { + res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" }); + res.end("Bad Request"); + return; + } + + const url = new URL(req.url, `http://${req.headers.host || "localhost"}`); + const requestPath = normalizePath(decodeURIComponent(url.pathname)); + const safePath = path.normalize(requestPath).replace(/^(\.\.[/\\])+/, ""); + + let filepath = path.join(DIST_DIR, safePath); + if (requestPath === "/" || requestPath === "") { + filepath = path.join(DIST_DIR, "index.html"); + } + + fs.stat(filepath, (err, stat) => { + if (!err && stat.isFile()) { + sendFile(res, filepath, requestPath); + return; + } + + sendFile(res, path.join(DIST_DIR, "index.html"), "/"); + }); + }) + .listen(PORT, () => { + console.log(`Serving dist on port ${PORT}`); + }); From 7c47b30c6f4209d1e1b125b4f8c0353134a40f1e Mon Sep 17 00:00:00 2001 From: Quintin Date: Thu, 23 Apr 2026 08:25:23 -0700 Subject: [PATCH 8/9] Increase keepBuffer, disable updateWhenZooming --- app/src/components/map/InteractionLayer.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/components/map/InteractionLayer.jsx b/app/src/components/map/InteractionLayer.jsx index d8d1964..a7ee613 100644 --- a/app/src/components/map/InteractionLayer.jsx +++ b/app/src/components/map/InteractionLayer.jsx @@ -107,8 +107,8 @@ const InteractionLayer = ({ baseStyles, interactionStyles }) => { interactive: true, getFeatureId: (feature) => feature.properties.uid, updateWhenIdle: true, - updateWhenZooming: true, - keepBuffer: 1, + updateWhenZooming: false, + keepBuffer: 2, preferCanvas: true, pane: "interactive", // Use the dedicated pane zIndex: 1, From bf313f2839889e88147812f4b37e0710b2eb4a2a Mon Sep 17 00:00:00 2001 From: Quintin Date: Mon, 4 May 2026 13:49:37 -0700 Subject: [PATCH 9/9] Update HelpGuide --- app/src/components/info/HelpGuide.jsx | 176 ++++++++++++++++++++++++-- 1 file changed, 164 insertions(+), 12 deletions(-) diff --git a/app/src/components/info/HelpGuide.jsx b/app/src/components/info/HelpGuide.jsx index 698b561..e6a989c 100644 --- a/app/src/components/info/HelpGuide.jsx +++ b/app/src/components/info/HelpGuide.jsx @@ -4,6 +4,26 @@ import "./HelpGuide.css"; const OGL_URL = "https://www2.gov.bc.ca/gov/content/data/policy-standards/data-policies/open-data/open-government-licence-bc"; +const CNRM_ESM2_1_URL = + "https://www.wdc-climate.de/ui/cmip6?input=CMIP6.CMIP.CNRM-CERFACS.CNRM-ESM2-1"; +const FGOALS_G3_URL = + "https://www.wdc-climate.de/ui/cmip6?input=CMIP6.CMIP.CAS.FGOALS-g3"; +const IPSL_CM6A_LR_URL = + "https://www.wdc-climate.de/ui/cmip6?input=CMIP6.CMIP.IPSL.IPSL-CM6A-LR"; +const MIROC_ES2L_URL = + "https://www.wdc-climate.de/ui/cmip6?input=CMIP6.ScenarioMIP.MIROC.MIROC-ES2L"; +const MPI_ESM1_2_HR_URL = + "https://mpimet.mpg.de/en/communication/news/development-of-a-high-resolution-earth-system-model-and-its-application-in-cmip6"; +const MRI_ESM2_0_URL = + "https://www.wdc-climate.de/ui/cmip6?input=CMIP6.CMIP.MRI.MRI-ESM2-0"; +const NORESM2_LM_URL = "https://noresm-docs.readthedocs.io/en/noresm2/"; +const TAIESM1_URL = "https://github.com/rceclccr/TaiESM-docs"; +const UKESM1_0_LL_URL = + "https://ukesm.ac.uk/cmip-es-documentation/ukesm1-0-ll/"; +const PNWNAMET_URL = + "https://www.uvic.ca/pcic/data-analysis-tools/data-portal/daily-gridded-meteorology/index.php"; +const SSP_URL = + "https://climatedata.ca/resource/understanding-shared-socio-economic-pathways-ssps/"; const HelpGuide = () => { const [isOpen, setIsOpen] = useState(false); @@ -92,6 +112,16 @@ const HelpGuide = () => { +
+

Feature Name Search

+
    +
  • Use top-left panel to search for features by name
  • +
  • Enter the lake or river name
  • +
  • Select a name from the drop-down of filtered names
  • +
  • The selected feature will be highlighted in light blue
  • +
+
+

Downloading Data

    @@ -107,40 +137,162 @@ const HelpGuide = () => {

    Variables

    • - Simulated outflows (m³/s) + Streamflow (m³/s)
    • - Observed outflows (m³/s) + Water Temperature or lake surface temperature (°C)
    • - Simulated reservoir inflows (m³/s) + Saturated dissolved oxygen (mg/L)
-

Models

+

Models (Forcing)

+

+ Downscaled Climate Projections +

+

+ Gridded Observations +

+ +
+ +
+

Scenarios

+

+ Climate Projections: Historical (1950-2014) + {" + "} + + Socio-economic Pathways + {" "} + (2015-2100) +

+
    +
  • Historical, SSP2-4.5
  • +
  • Historical, SSP5-8.5
  • +
+

+ Gridded Observations: Historical only + (1945-2012) +

+
    +
  • Historical (PNWNAmet only)
-

Credits & licensing

+

Credits & Licensing

This application uses data and services from the BC Geographic Warehouse (DataBC).