Show current weather on the Overview
Add a weather card to the Web App Overview, wired like the OpenSky live-map
overlay and backed by the OpenWeather plugin.
- API Server: GET /api/integrations/openweather/current resolves the
caller's cascade, gates it (master/org/personal opt-in/key), and returns
trimmed current conditions for the configured or a supplied ?lat=&lon=
point; off/keyless returns {unavailable, detail} so the card degrades.
- BFF relay (forwards the location override) + route; api.js client.
- Dashboard: a Weather card stacked above Schedule showing an emoji
condition, temperature in the resolved unit, description, location, and a
feels-like/wind/humidity/cloud grid. Location follows the same cascade as
the map (drone -> phone -> browser -> default) without prompting for geo;
refreshes every 10 min while on Overview.
- validLatLon test; rebuilt embedded frontend.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
522fe450eb
commit
5960fb4806
11 files changed
+348
-25
No files matched your search
@@ -344,6 +344,18 @@ func (a *App) handleOpenWeatherHealth(w http.ResponseWriter, r *http.Request) {
|
||||
a.doRelay(w, req)
|
||||
}
|
||||
|
||||
// GET /bff/integrations/openweather/current → API Server current conditions for the
|
||||
// Overview weather card. Forwards the optional ?lat=&lon= location override.
|
||||
func (a *App) handleOpenWeatherCurrent(w http.ResponseWriter, r *http.Request) {
|
||||
target := a.apiBaseFor(r) + "/api/integrations/openweather/current"
|
||||
if r.URL.RawQuery != "" {
|
||||
target += "?" + r.URL.RawQuery
|
||||
}
|
||||
req, _ := http.NewRequest(http.MethodGet, target, nil)
|
||||
req.Header.Set("Authorization", tokenOf(r))
|
||||
a.doRelay(w, req)
|
||||
}
|
||||
|
||||
// GET /bff/users → API Server /api/users (admin only, enforced upstream)
|
||||
func (a *App) handleListUsers(w http.ResponseWriter, r *http.Request) {
|
||||
req, _ := http.NewRequest(http.MethodGet, a.apiBaseFor(r)+"/api/users", nil)
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
(function(){const i=document.createElement("link").relList;if(i&&i.supports&&i.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const f of u)if(f.type==="childList")for(const h of f.addedNodes)h.tagName==="LINK"&&h.rel==="modulepreload"&&l(h)}).observe(document,{childList:!0,subtree:!0});function s(u){const f={};return u.integrity&&(f.integrity=u.integrity),u.referrerPolicy&&(f.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?f.credentials="include":u.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function l(u){if(u.ep)return;u.ep=!0;const f=s(u);fetch(u.href,f)}})();/**
|
||||
* @vue/shared v3.5.39
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/function Xr(t){const i=Object.create(null);for(const s of t.split(","))i[s]=1;return s=>s in i}const yt={},qo=[],ni=()=>{},Ou=()=>!1,Ha=t=>t.charCodeAt(0)===111&&t.charCodeAt(1)===110&&(t.charCodeAt(2)>122||t.charCodeAt(2)<97),ja=t=>t.startsWith("onUpdate:"),Bt=Object.assign,Qr=(t,i)=>{const s=t.indexOf(i);s>-1&&t.splice(s,1)},pd=Object.prototype.hasOwnProperty,mt=(t,i)=>pd.call(t,i),Fe=Array.isArray,Yo=t=>Xs(t)==="[object Map]",is=t=>Xs(t)==="[object Set]",Ll=t=>Xs(t)==="[object Date]",Ye=t=>typeof t=="function",Ct=t=>typeof t=="string",Wn=t=>typeof t=="symbol",gt=t=>t!==null&&typeof t=="object",zu=t=>(gt(t)||Ye(t))&&Ye(t.then)&&Ye(t.catch),Iu=Object.prototype.toString,Xs=t=>Iu.call(t),md=t=>Xs(t).slice(8,-1),$u=t=>Xs(t)==="[object Object]",el=t=>Ct(t)&&t!=="NaN"&&t[0]!=="-"&&""+parseInt(t,10)===t,Ds=Xr(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Wa=t=>{const i=Object.create(null);return(s=>i[s]||(i[s]=t(s)))},gd=/-\w/g,Hn=Wa(t=>t.replace(gd,i=>i.slice(1).toUpperCase())),vd=/\B([A-Z])/g,ji=Wa(t=>t.replace(vd,"-$1").toLowerCase()),Nu=Wa(t=>t.charAt(0).toUpperCase()+t.slice(1)),xr=Wa(t=>t?`on${Nu(t)}`:""),ti=(t,i)=>!Object.is(t,i),Aa=(t,...i)=>{for(let s=0;s<t.length;s++)t[s](...i)},Du=(t,i,s,l=!1)=>{Object.defineProperty(t,i,{configurable:!0,enumerable:!1,writable:l,value:s})},Ka=t=>{const i=parseFloat(t);return isNaN(i)?t:i},_d=t=>{const i=Ct(t)?Number(t):NaN;return isNaN(i)?t:i};let Ml;const Ga=()=>Ml||(Ml=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function wo(t){if(Fe(t)){const i={};for(let s=0;s<t.length;s++){const l=t[s],u=Ct(l)?wd(l):wo(l);if(u)for(const f in u)i[f]=u[f]}return i}else if(Ct(t)||gt(t))return t}const bd=/;(?![^(]*\))/g,yd=/:([^]+)/,xd=/\/\*[^]*?\*\//g;function wd(t){const i={};return t.replace(xd,"").split(bd).forEach(s=>{if(s){const l=s.split(yd);l.length>1&&(i[l[0].trim()]=l[1].trim())}}),i}function Ae(t){let i="";if(Ct(t))i=t;else if(Fe(t))for(let s=0;s<t.length;s++){const l=Ae(t[s]);l&&(i+=l+" ")}else if(gt(t))for(const s in t)t[s]&&(i+=s+" ");return i.trim()}const kd="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",Sd=Xr(kd);function Fu(t){return!!t||t===""}function Td(t,i){if(t.length!==i.length)return!1;let s=!0;for(let l=0;s&&l<t.length;l++)s=Vi(t[l],i[l]);return s}function Vi(t,i){if(t===i)return!0;let s=Ll(t),l=Ll(i);if(s||l)return s&&l?t.getTime()===i.getTime():!1;if(s=Wn(t),l=Wn(i),s||l)return t===i;if(s=Fe(t),l=Fe(i),s||l)return s&&l?Td(t,i):!1;if(s=gt(t),l=gt(i),s||l){if(!s||!l)return!1;const u=Object.keys(t).length,f=Object.keys(i).length;if(u!==f)return!1;for(const h in t){const _=t.hasOwnProperty(h),y=i.hasOwnProperty(h);if(_&&!y||!_&&y||!Vi(t[h],i[h]))return!1}}return String(t)===String(i)}function tl(t,i){return t.findIndex(s=>Vi(s,i))}const Ru=t=>!!(t&&t.__v_isRef===!0),k=t=>Ct(t)?t:t==null?"":Fe(t)||gt(t)&&(t.toString===Iu||!Ye(t.toString))?Ru(t)?k(t.value):JSON.stringify(t,Bu,2):String(t),Bu=(t,i)=>Ru(i)?Bu(t,i.value):Yo(i)?{[`Map(${i.size})`]:[...i.entries()].reduce((s,[l,u],f)=>(s[wr(l,f)+" =>"]=u,s),{})}:is(i)?{[`Set(${i.size})`]:[...i.values()].map(s=>wr(s))}:Wn(i)?wr(i):gt(i)&&!Fe(i)&&!$u(i)?String(i):i,wr=(t,i="")=>{var s;return Wn(t)?`Symbol(${(s=t.description)!=null?s:i})`:t};/**
|
||||
* @vue/reactivity v3.5.39
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/let Vt;class Pd{constructor(i=!1){this.detached=i,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this._warnOnRun=!0,this.__v_skip=!0,!i&&Vt&&(Vt.active?(this.parent=Vt,this.index=(Vt.scopes||(Vt.scopes=[])).push(this)-1):(this._active=!1,this._warnOnRun=!1))}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let i,s;if(this.scopes)for(i=0,s=this.scopes.length;i<s;i++)this.scopes[i].pause();for(i=0,s=this.effects.length;i<s;i++)this.effects[i].pause()}}resume(){if(this._active&&this._isPaused){this._isPaused=!1;let i,s;if(this.scopes)for(i=0,s=this.scopes.length;i<s;i++)this.scopes[i].resume();for(i=0,s=this.effects.length;i<s;i++)this.effects[i].resume()}}run(i){if(this._active){const s=Vt;try{return Vt=this,i()}finally{Vt=s}}}on(){++this._on===1&&(this.prevScope=Vt,Vt=this)}off(){if(this._on>0&&--this._on===0){if(Vt===this)Vt=this.prevScope;else{let i=Vt;for(;i;){if(i.prevScope===this){i.prevScope=this.prevScope;break}i=i.prevScope}}this.prevScope=void 0}}stop(i){if(this._active){this._active=!1;let s,l;for(s=0,l=this.effects.length;s<l;s++)this.effects[s].stop();for(this.effects.length=0,s=0,l=this.cleanups.length;s<l;s++)this.cleanups[s]();if(this.cleanups.length=0,this.scopes){for(s=0,l=this.scopes.length;s<l;s++)this.scopes[s].stop(!0);this.scopes.length=0}if(!this.detached&&this.parent&&!i){const u=this.parent.scopes.pop();u&&u!==this&&(this.parent.scopes[this.index]=u,u.index=this.index)}this.parent=void 0}}}function Cd(){return Vt}let kt;const kr=new WeakSet;class Uu{constructor(i){this.fn=i,this.deps=void 0,this.depsTail=void 0,this.flags=5,this.next=void 0,this.cleanup=void 0,this.scheduler=void 0,Vt&&(Vt.active?Vt.effects.push(this):this.flags&=-2)}pause(){this.flags|=64}resume(){this.flags&64&&(this.flags&=-65,kr.has(this)&&(kr.delete(this),this.trigger()))}notify(){this.flags&2&&!(this.flags&32)||this.flags&8||Zu(this)}run(){if(!(this.flags&1))return this.fn();this.flags|=2,Al(this),Hu(this);const i=kt,s=jn;kt=this,jn=!0;try{return this.fn()}finally{ju(this),kt=i,jn=s,this.flags&=-3}}stop(){if(this.flags&1){for(let i=this.deps;i;i=i.nextDep)ol(i);this.deps=this.depsTail=void 0,Al(this),this.onStop&&this.onStop(),this.flags&=-2}}trigger(){this.flags&64?kr.add(this):this.scheduler?this.scheduler():this.runIfDirty()}runIfDirty(){$r(this)&&this.run()}get dirty(){return $r(this)}}let Vu=0,Fs,Rs;function Zu(t,i=!1){if(t.flags|=8,i){t.next=Rs,Rs=t;return}t.next=Fs,Fs=t}function nl(){Vu++}function il(){if(--Vu>0)return;if(Rs){let i=Rs;for(Rs=void 0;i;){const s=i.next;i.next=void 0,i.flags&=-9,i=s}}let t;for(;Fs;){let i=Fs;for(Fs=void 0;i;){const s=i.next;if(i.next=void 0,i.flags&=-9,i.flags&1)try{i.trigger()}catch(l){t||(t=l)}i=s}}if(t)throw t}function Hu(t){for(let i=t.deps;i;i=i.nextDep)i.version=-1,i.prevActiveLink=i.dep.activeLink,i.dep.activeLink=i}function ju(t){let i,s=t.depsTail,l=s;for(;l;){const u=l.prevDep;l.version===-1?(l===s&&(s=u),ol(l),Ld(l)):i=l,l.dep.activeLink=l.prevActiveLink,l.prevActiveLink=void 0,l=u}t.deps=i,t.depsTail=s}function $r(t){for(let i=t.deps;i;i=i.nextDep)if(i.dep.version!==i.version||i.dep.computed&&(Wu(i.dep.computed)||i.dep.version!==i.version))return!0;return!!t._dirty}function Wu(t){if(t.flags&4&&!(t.flags&16)||(t.flags&=-17,t.globalVersion===Hs)||(t.globalVersion=Hs,!t.isSSR&&t.flags&128&&(!t.deps&&!t._dirty||!$r(t))))return;t.flags|=2;const i=t.dep,s=kt,l=jn;kt=t,jn=!0;try{Hu(t);const u=t.fn(t._value);(i.version===0||ti(u,t._value))&&(t.flags|=128,t._value=u,i.version++)}catch(u){throw i.version++,u}finally{kt=s,jn=l,ju(t),t.flags&=-3}}function ol(t,i=!1){const{dep:s,prevSub:l,nextSub:u}=t;if(l&&(l.nextSub=u,t.prevSub=void 0),u&&(u.prevSub=l,t.nextSub=void 0),s.subs===t&&(s.subs=l,!l&&s.computed)){s.computed.flags&=-5;for(let f=s.computed.deps;f;f=f.nextDep)ol(f,!0)}!i&&!--s.sc&&s.map&&s.map.delete(s.key)}function Ld(t){const{prevDep:i,nextDep:s}=t;i&&(i.nextDep=s,t.prevDep=void 0),s&&(s.prevDep=i,t.nextDep=void 0)}let jn=!0;const Ku=[];function ii(){Ku.push(jn),jn=!1}function oi(){const t=Ku.pop();jn=t===void 0?!0:t}function Al(t){const{cleanup:i}=t;if(t.cleanup=void 0,i){const s=kt;kt=void 0;try{i()}finally{kt=s}}}let Hs=0;class Md{constructor(i,s){this.sub=i,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class sl{constructor(i){this.computed=i,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(i){if(!kt||!jn||kt===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==kt)s=this.activeLink=new Md(kt,this),kt.deps?(s.prevDep=kt.depsTail,kt.depsTail.nextDep=s,kt.depsTail=s):kt.deps=kt.depsTail=s,Gu(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const l=s.nextDep;l.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=l),s.prevDep=kt.depsTail,s.nextDep=void 0,kt.depsTail.nextDep=s,kt.depsTail=s,kt.deps===s&&(kt.deps=l)}return s}trigger(i){this.versiLine truncated
|
||||
* @vue/runtime-core v3.5.39
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/function Qs(t,i,s,l){try{return l?t(...l):t()}catch(u){Ya(u,i,s)}}function Dn(t,i,s,l){if(Ye(t)){const u=Qs(t,i,s,l);return u&&zu(u)&&u.catch(f=>{Ya(f,i,s)}),u}if(Fe(t)){const u=[];for(let f=0;f<t.length;f++)u.push(Dn(t[f],i,s,l));return u}}function Ya(t,i,s,l=!0){const u=i?i.vnode:null,{errorHandler:f,throwUnhandledErrorInProduction:h}=i&&i.appContext.config||yt;if(i){let _=i.parent;const y=i.proxy,C=`https://vuejs.org/error-reference/#runtime-${s}`;for(;_;){const T=_.ec;if(T){for(let A=0;A<T.length;A++)if(T[A](t,y,C)===!1)return}_=_.parent}if(f){ii(),Qs(f,null,10,[t,y,C]),oi();return}}ef(t,s,u,l,h)}function ef(t,i,s,l=!0,u=!1){if(u)throw t;console.error(t)}const sn=[];let Xn=-1;const Jo=[];let Ui=null,Go=0;const nc=Promise.resolve();let za=null;function ic(t){const i=za||nc;return t?i.then(this?t.bind(this):t):i}function tf(t){let i=Xn+1,s=sn.length;for(;i<s;){const l=i+s>>>1,u=sn[l],f=Ws(u);f<t||f===t&&u.flags&2?i=l+1:s=l}return i}function ul(t){if(!(t.flags&1)){const i=Ws(t),s=sn[sn.length-1];!s||!(t.flags&2)&&i>=Ws(s)?sn.push(t):sn.splice(tf(i),0,t),t.flags|=1,oc()}}function oc(){za||(za=nc.then(ac))}function nf(t){Fe(t)?Jo.push(...t):Ui&&t.id===-1?Ui.splice(Go+1,0,t):t.flags&1||(Jo.push(t),t.flags|=1),oc()}function Ol(t,i,s=Xn+1){for(;s<sn.length;s++){const l=sn[s];if(l&&l.flags&2){if(t&&l.id!==t.uid)continue;sn.splice(s,1),s--,l.flags&4&&(l.flags&=-2),l(),l.flags&4||(l.flags&=-2)}}}function sc(t){if(Jo.length){const i=[...new Set(Jo)].sort((s,l)=>Ws(s)-Ws(l));if(Jo.length=0,Ui){Ui.push(...i);return}for(Ui=i,Go=0;Go<Ui.length;Go++){const s=Ui[Go];s.flags&4&&(s.flags&=-2),s.flags&8||s(),s.flags&=-2}Ui=null,Go=0}}const Ws=t=>t.id==null?t.flags&2?-1:1/0:t.id;function ac(t){try{for(Xn=0;Xn<sn.length;Xn++){const i=sn[Xn];i&&!(i.flags&8)&&(i.flags&4&&(i.flags&=-2),Qs(i,i.i,i.i?15:14),i.flags&4||(i.flags&=-2))}}finally{for(;Xn<sn.length;Xn++){const i=sn[Xn];i&&(i.flags&=-2)}Xn=-1,sn.length=0,sc(),za=null,(sn.length||Jo.length)&&ac()}}let Yt=null,rc=null;function Ia(t){const i=Yt;return Yt=t,rc=t&&t.type.__scopeId||null,i}function xe(t,i=Yt,s){if(!i||t._n)return t;const l=(...u)=>{l._d&&Da(-1);const f=Ia(i);let h;try{h=t(...u)}finally{Ia(f),l._d&&Da(1)}return h};return l._n=!0,l._c=!0,l._d=!0,l}function ee(t,i){if(Yt===null)return t;const s=tr(Yt),l=t.dirs||(t.dirs=[]);for(let u=0;u<i.length;u++){let[f,h,_,y=yt]=i[u];f&&(Ye(f)&&(f={mounted:f,updated:f}),f.deep&&yi(h),l.push({dir:f,instance:s,value:h,oldValue:void 0,arg:_,modifiers:y}))}return t}function ho(t,i,s,l){const u=t.dirs,f=i&&i.dirs;for(let h=0;h<u.length;h++){const _=u[h];f&&(_.oldValue=f[h].value);let y=_.dir[l];y&&(ii(),Dn(y,s,8,[t.el,_,t,i]),oi())}}function lc(t,i){if(an){let s=an.provides;const l=an.parent&&an.parent.provides;l===s&&(s=an.provides=Object.create(l)),s[t]=i}}function Bs(t,i,s=!1){const l=Bc();if(l||Qo){let u=Qo?Qo._context.provides:l?l.parent==null||l.ce?l.vnode.appContext&&l.vnode.appContext.provides:l.parent.provides:void 0;if(u&&t in u)return u[t];if(arguments.length>1)return s&&Ye(i)?i.call(l&&l.proxy):i}}const of=Symbol.for("v-scx"),sf=()=>Bs(of);function Nt(t,i,s){return uc(t,i,s)}function uc(t,i,s=yt){const{immediate:l,deep:u,flush:f,once:h}=s,_=Bt({},s),y=i&&l||!i&&f!=="post";let C;if(Ys){if(f==="sync"){const B=sf();C=B.__watcherHandles||(B.__watcherHandles=[])}else if(!y){const B=()=>{};return B.stop=ni,B.resume=ni,B.pause=ni,B}}const T=an;_.call=(B,j,F)=>Dn(B,T,j,F);let A=!1;f==="post"?_.scheduler=B=>{on(B,T&&T.suspense)}:f!=="sync"&&(A=!0,_.scheduler=(B,j)=>{j?B():ul(B)}),_.augmentJob=B=>{i&&(B.flags|=4),A&&(B.flags|=2,T&&(B.id=T.uid,B.i=T))};const R=Qd(t,i,_);return Ys&&(C?C.push(R):y&&R()),R}function af(t,i,s){const l=this.proxy,u=Ct(t)?t.includes(".")?cc(l,t):()=>l[t]:t.bind(l,l);let f;Ye(i)?f=i:(f=i.handler,s=i);const h=ea(this),_=uc(u,f.bind(l),s);return h(),_}function cc(t,i){const s=i.split(".");return()=>{let l=t;for(let u=0;u<s.length&&l;u++)l=l[s[u]];return l}}const Bi=new WeakMap,dc=Symbol("_vte"),fc=t=>t.__isTeleport,_o=t=>t&&(t.disabled||t.disabled===""),rf=t=>t&&(t.defer||t.defer===""),zl=t=>typeof SVGElement<"u"&&t instanceof SVGElement,Il=t=>typeof MathMLElement=="function"&&t instanceof MathMLElement,Br=(t,i)=>{const s=t&&t.to;return Ct(s)?i?i(s):null:s},lf={name:"Teleport",__isTeleport:!0,process(t,i,s,l,u,f,h,_,y,C){const{mc:T,pc:A,pbc:R,o:{insert:B,querySelector:j,createText:F,createComment:pe,parentNode:me}}=C,Y=_o(i.props);let{dynamicChildren:Le}=i;const fe=(Ie,Ge,we)=>{Ie.shapeFlag&16&&T(Ie.children,Ge,we,u,f,h,_,y)},Ue=(Ie=i)=>{const Ge=_o(Ie.props),we=Ie.target=Br(Ie.props,j),Te=Ur(we,Ie,F,B);we&&(h!=="svg"&&zl(we)?h="svg":h!=="mathml"&&Il(we)&&(h="mathml"),u&&u.isCE&&(u.ce._teleportTargets||(u.ce._teleportTargets=new Set)).add(we),Ge||(fe(Ie,we,Te),zs(Ie,!1)))},Ne=Ie=>{const Ge=()=>{if(Bi.get(Ie)===Ge){if(Bi.delete(Ie),_o(Ie.props)){const we=me(Ie.el)||s;fe(Ie,we,Ie.anchor),zs(Ie,!0)}Ue(Ie)}};Bi.set(Ie,Ge),on(Ge,f)};if(t==null){const Ie=i.el=F(""),Ge=i.anchor=F("");if(B(Ie,s,l),B(Ge,s,l),rf
Line truncated
|
||||
* @vue/runtime-dom v3.5.39
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/let Gr;const Gl=typeof window<"u"&&window.trustedTypes;if(Gl)try{Gr=Gl.createPolicy("vue",{createHTML:t=>t})}catch{}const Zc=Gr?t=>Gr.createHTML(t):t=>t,fh="http://www.w3.org/2000/svg",hh="http://www.w3.org/1998/Math/MathML",vi=typeof document<"u"?document:null,ql=vi&&vi.createElement("template"),ph={insert:(t,i,s)=>{i.insertBefore(t,s||null)},remove:t=>{const i=t.parentNode;i&&i.removeChild(t)},createElement:(t,i,s,l)=>{const u=i==="svg"?vi.createElementNS(fh,t):i==="mathml"?vi.createElementNS(hh,t):s?vi.createElement(t,{is:s}):vi.createElement(t);return t==="select"&&l&&l.multiple!=null&&u.setAttribute("multiple",l.multiple),u},createText:t=>vi.createTextNode(t),createComment:t=>vi.createComment(t),setText:(t,i)=>{t.nodeValue=i},setElementText:(t,i)=>{t.textContent=i},parentNode:t=>t.parentNode,nextSibling:t=>t.nextSibling,querySelector:t=>vi.querySelector(t),setScopeId(t,i){t.setAttribute(i,"")},insertStaticContent(t,i,s,l,u,f){const h=s?s.previousSibling:i.lastChild;if(u&&(u===f||u.nextSibling))for(;i.insertBefore(u.cloneNode(!0),s),!(u===f||!(u=u.nextSibling)););else{ql.innerHTML=Zc(l==="svg"?`<svg>${t}</svg>`:l==="mathml"?`<math>${t}</math>`:t);const _=ql.content;if(l==="svg"||l==="mathml"){const y=_.firstChild;for(;y.firstChild;)_.appendChild(y.firstChild);_.removeChild(y)}i.insertBefore(_,s)}return[h?h.nextSibling:i.firstChild,s?s.previousSibling:i.lastChild]}},Fi="transition",Es="animation",Js=Symbol("_vtc"),Hc={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},mh=Bt({},hc,Hc),gh=t=>(t.displayName="Transition",t.props=mh,t),vh=gh((t,{slots:i})=>ch(hf,_h(t),i)),mo=(t,i=[])=>{Fe(t)?t.forEach(s=>s(...i)):t&&t(...i)},Yl=t=>t?Fe(t)?t.some(i=>i.length>1):t.length>1:!1;function _h(t){const i={};for(const ie in t)ie in Hc||(i[ie]=t[ie]);if(t.css===!1)return i;const{name:s="v",type:l,duration:u,enterFromClass:f=`${s}-enter-from`,enterActiveClass:h=`${s}-enter-active`,enterToClass:_=`${s}-enter-to`,appearFromClass:y=f,appearActiveClass:C=h,appearToClass:T=_,leaveFromClass:A=`${s}-leave-from`,leaveActiveClass:R=`${s}-leave-active`,leaveToClass:B=`${s}-leave-to`}=t,j=bh(u),F=j&&j[0],pe=j&&j[1],{onBeforeEnter:me,onEnter:Y,onEnterCancelled:Le,onLeave:fe,onLeaveCancelled:Ue,onBeforeAppear:Ne=me,onAppear:Ie=Y,onAppearCancelled:Ge=Le}=i,we=(ie,je,oe,We)=>{ie._enterCancelled=We,go(ie,je?T:_),go(ie,je?C:h),oe&&oe()},Te=(ie,je)=>{ie._isLeaving=!1,go(ie,A),go(ie,B),go(ie,R),je&&je()},ze=ie=>(je,oe)=>{const We=ie?Ie:Y,ue=()=>we(je,ie,oe);mo(We,[je,ue]),Jl(()=>{go(je,ie?y:f),gi(je,ie?T:_),Yl(We)||Xl(je,l,F,ue)})};return Bt(i,{onBeforeEnter(ie){mo(me,[ie]),gi(ie,f),gi(ie,h)},onBeforeAppear(ie){mo(Ne,[ie]),gi(ie,y),gi(ie,C)},onEnter:ze(!1),onAppear:ze(!0),onLeave(ie,je){ie._isLeaving=!0;const oe=()=>Te(ie,je);gi(ie,A),ie._enterCancelled?(gi(ie,R),tu(ie)):(tu(ie),gi(ie,R)),Jl(()=>{ie._isLeaving&&(go(ie,A),gi(ie,B),Yl(fe)||Xl(ie,l,pe,oe))}),mo(fe,[ie,oe])},onEnterCancelled(ie){we(ie,!1,void 0,!0),mo(Le,[ie])},onAppearCancelled(ie){we(ie,!0,void 0,!0),mo(Ge,[ie])},onLeaveCancelled(ie){Te(ie),mo(Ue,[ie])}})}function bh(t){if(t==null)return null;if(gt(t))return[Ar(t.enter),Ar(t.leave)];{const i=Ar(t);return[i,i]}}function Ar(t){return _d(t)}function gi(t,i){i.split(/\s+/).forEach(s=>s&&t.classList.add(s)),(t[Js]||(t[Js]=new Set)).add(i)}function go(t,i){i.split(/\s+/).forEach(l=>l&&t.classList.remove(l));const s=t[Js];s&&(s.delete(i),s.size||(t[Js]=void 0))}function Jl(t){requestAnimationFrame(()=>{requestAnimationFrame(t)})}let yh=0;function Xl(t,i,s,l){const u=t._endId=++yh,f=()=>{u===t._endId&&l()};if(s!=null)return setTimeout(f,s);const{type:h,timeout:_,propCount:y}=xh(t,i);if(!h)return l();const C=h+"end";let T=0;const A=()=>{t.removeEventListener(C,R),f()},R=B=>{B.target===t&&++T>=y&&A()};setTimeout(()=>{T<y&&A()},_+1),t.addEventListener(C,R)}function xh(t,i){const s=window.getComputedStyle(t),l=j=>(s[j]||"").split(", "),u=l(`${Fi}Delay`),f=l(`${Fi}Duration`),h=Ql(u,f),_=l(`${Es}Delay`),y=l(`${Es}Duration`),C=Ql(_,y);let T=null,A=0,R=0;i===Fi?h>0&&(T=Fi,A=h,R=f.length):i===Es?C>0&&(T=Es,A=C,R=y.length):(A=Math.max(h,C),T=A>0?h>C?Fi:Es:null,R=T?T===Fi?f.length:y.length:0);const B=T===Fi&&/\b(?:transform|all)(?:,|$)/.test(l(`${Fi}Property`).toString());return{type:T,timeout:A,propCount:R,hasTransform:B}}function Ql(t,i){for(;t.length<i.length;)t=t.concat(t);return Math.max(...i.map((s,l)=>eu(s)+eu(t[l])))}function eu(t){return t==="auto"?0:Number(t.slice(0,-1).replace(",","."))*1e3}function tu(t){return(t?t.ownerDocument:document).body.offsetHeight}function wh(t,i,s){const l=t[Js];l&&(i=(i?[i,...l]:[...l]).join(" ")),i==null?t.removeAttribute("class"):s?t.setAttribute("class",i):t.className=i}const Ba=Symbol("_vod"),jc=Symbol("_vsh"),kh={name:"show",beforeMount(t,{value:i},{transition:s
Line truncated
|
||||
* Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
|
||||
* (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
|
||||
*/var rm=Ns.exports,Tu;function lm(){return Tu||(Tu=1,(function(t,i){(function(s,l){l(i)})(rm,(function(s){var l="1.9.4";function u(e){var n,o,r,d;for(o=1,r=arguments.length;o<r;o++){d=arguments[o];for(n in d)e[n]=d[n]}return e}var f=Object.create||(function(){function e(){}return function(n){return e.prototype=n,new e}})();function h(e,n){var o=Array.prototype.slice;if(e.bind)return e.bind.apply(e,o.call(arguments,1));var r=o.call(arguments,2);return function(){return e.apply(n,r.length?r.concat(o.call(arguments)):arguments)}}var _=0;function y(e){return"_leaflet_id"in e||(e._leaflet_id=++_),e._leaflet_id}function C(e,n,o){var r,d,v,P;return P=function(){r=!1,d&&(v.apply(o,d),d=!1)},v=function(){r?d=arguments:(e.apply(o,arguments),setTimeout(P,n),r=!0)},v}function T(e,n,o){var r=n[1],d=n[0],v=r-d;return e===r&&o?e:((e-d)%v+v)%v+d}function A(){return!1}function R(e,n){if(n===!1)return e;var o=Math.pow(10,n===void 0?6:n);return Math.round(e*o)/o}function B(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function j(e){return B(e).split(/\s+/)}function F(e,n){Object.prototype.hasOwnProperty.call(e,"options")||(e.options=e.options?f(e.options):{});for(var o in n)e.options[o]=n[o];return e.options}function pe(e,n,o){var r=[];for(var d in e)r.push(encodeURIComponent(o?d.toUpperCase():d)+"="+encodeURIComponent(e[d]));return(!n||n.indexOf("?")===-1?"?":"&")+r.join("&")}var me=/\{ *([\w_ -]+) *\}/g;function Y(e,n){return e.replace(me,function(o,r){var d=n[r];if(d===void 0)throw new Error("No value provided for variable "+o);return typeof d=="function"&&(d=d(n)),d})}var Le=Array.isArray||function(e){return Object.prototype.toString.call(e)==="[object Array]"};function fe(e,n){for(var o=0;o<e.length;o++)if(e[o]===n)return o;return-1}var Ue="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";function Ne(e){return window["webkit"+e]||window["moz"+e]||window["ms"+e]}var Ie=0;function Ge(e){var n=+new Date,o=Math.max(0,16-(n-Ie));return Ie=n+o,window.setTimeout(e,o)}var we=window.requestAnimationFrame||Ne("RequestAnimationFrame")||Ge,Te=window.cancelAnimationFrame||Ne("CancelAnimationFrame")||Ne("CancelRequestAnimationFrame")||function(e){window.clearTimeout(e)};function ze(e,n,o){if(o&&we===Ge)e.call(n);else return we.call(window,h(e,n))}function ie(e){e&&Te.call(window,e)}var je={__proto__:null,extend:u,create:f,bind:h,get lastId(){return _},stamp:y,throttle:C,wrapNum:T,falseFn:A,formatNum:R,trim:B,splitWords:j,setOptions:F,getParamString:pe,template:Y,isArray:Le,indexOf:fe,emptyImageUrl:Ue,requestFn:we,cancelFn:Te,requestAnimFrame:ze,cancelAnimFrame:ie};function oe(){}oe.extend=function(e){var n=function(){F(this),this.initialize&&this.initialize.apply(this,arguments),this.callInitHooks()},o=n.__super__=this.prototype,r=f(o);r.constructor=n,n.prototype=r;for(var d in this)Object.prototype.hasOwnProperty.call(this,d)&&d!=="prototype"&&d!=="__super__"&&(n[d]=this[d]);return e.statics&&u(n,e.statics),e.includes&&(We(e.includes),u.apply(null,[r].concat(e.includes))),u(r,e),delete r.statics,delete r.includes,r.options&&(r.options=o.options?f(o.options):{},u(r.options,e.options)),r._initHooks=[],r.callInitHooks=function(){if(!this._initHooksCalled){o.callInitHooks&&o.callInitHooks.call(this),this._initHooksCalled=!0;for(var v=0,P=r._initHooks.length;v<P;v++)r._initHooks[v].call(this)}},n},oe.include=function(e){var n=this.prototype.options;return u(this.prototype,e),e.options&&(this.prototype.options=n,this.mergeOptions(e.options)),this},oe.mergeOptions=function(e){return u(this.prototype.options,e),this},oe.addInitHook=function(e){var n=Array.prototype.slice.call(arguments,1),o=typeof e=="function"?e:function(){this[e].apply(this,n)};return this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(o),this};function We(e){if(!(typeof L>"u"||!L||!L.Mixin)){e=Le(e)?e:[e];for(var n=0;n<e.length;n++)e[n]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",new Error().stack)}}var ue={on:function(e,n,o){if(typeof e=="object")for(var r in e)this._on(r,e[r],n);else{e=j(e);for(var d=0,v=e.length;d<v;d++)this._on(e[d],n,o)}return this},off:function(e,n,o){if(!arguments.length)delete this._events;else if(typeof e=="object")for(var r in e)this._off(r,e[r],n);else{e=j(e);for(var d=arguments.length===1,v=0,P=e.length;v<P;v++)d?this._off(e[v]):this._off(e[v],n,o)}return this},_on:function(e,n,o,r){if(typeof n!="function"){console.warn("wrong listener type: "+typeof n);return}if(this._listens(e,n,o)===!1){o===this&&(o=void 0);var d={fn:n,ctx:o};r&&(d.once=!0),this._events=this._events||{},this._events[e]=this._events[e]||[],this._events[e].push(d)}},_off:function(e,n,o){var r,d,v;if(this._events&&(r=this._events[e],!!r)){if(arguments.length===1){if(this._firingCount)for(d=0,v=r.length;d<v;d++)r[d].fn=A;delete this._events[e];return}if(typeof n!="function"){console.warn("wrong listener type:Line truncated
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
(function(){const i=document.createElement("link").relList;if(i&&i.supports&&i.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const f of u)if(f.type==="childList")for(const h of f.addedNodes)h.tagName==="LINK"&&h.rel==="modulepreload"&&l(h)}).observe(document,{childList:!0,subtree:!0});function s(u){const f={};return u.integrity&&(f.integrity=u.integrity),u.referrerPolicy&&(f.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?f.credentials="include":u.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function l(u){if(u.ep)return;u.ep=!0;const f=s(u);fetch(u.href,f)}})();/**
|
||||
* @vue/shared v3.5.39
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/function Xr(t){const i=Object.create(null);for(const s of t.split(","))i[s]=1;return s=>s in i}const wt={},es=[],di=()=>{},Ou=()=>!1,ja=t=>t.charCodeAt(0)===111&&t.charCodeAt(1)===110&&(t.charCodeAt(2)>122||t.charCodeAt(2)<97),Wa=t=>t.startsWith("onUpdate:"),Ht=Object.assign,Qr=(t,i)=>{const s=t.indexOf(i);s>-1&&t.splice(s,1)},pd=Object.prototype.hasOwnProperty,vt=(t,i)=>pd.call(t,i),De=Array.isArray,ts=t=>ea(t)==="[object Map]",ls=t=>ea(t)==="[object Set]",Ll=t=>ea(t)==="[object Date]",Ge=t=>typeof t=="function",Ct=t=>typeof t=="string",ti=t=>typeof t=="symbol",_t=t=>t!==null&&typeof t=="object",zu=t=>(_t(t)||Ge(t))&&Ge(t.then)&&Ge(t.catch),Iu=Object.prototype.toString,ea=t=>Iu.call(t),md=t=>ea(t).slice(8,-1),$u=t=>ea(t)==="[object Object]",el=t=>Ct(t)&&t!=="NaN"&&t[0]!=="-"&&""+parseInt(t,10)===t,Rs=Xr(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Ka=t=>{const i=Object.create(null);return(s=>i[s]||(i[s]=t(s)))},gd=/-\w/g,Qn=Ka(t=>t.replace(gd,i=>i.slice(1).toUpperCase())),vd=/\B([A-Z])/g,eo=Ka(t=>t.replace(vd,"-$1").toLowerCase()),Nu=Ka(t=>t.charAt(0).toUpperCase()+t.slice(1)),xr=Ka(t=>t?`on${Nu(t)}`:""),ci=(t,i)=>!Object.is(t,i),Ea=(t,...i)=>{for(let s=0;s<t.length;s++)t[s](...i)},Du=(t,i,s,l=!1)=>{Object.defineProperty(t,i,{configurable:!0,enumerable:!1,writable:l,value:s})},Ga=t=>{const i=parseFloat(t);return isNaN(i)?t:i},_d=t=>{const i=Ct(t)?Number(t):NaN;return isNaN(i)?t:i};let Al;const qa=()=>Al||(Al=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Mo(t){if(De(t)){const i={};for(let s=0;s<t.length;s++){const l=t[s],u=Ct(l)?wd(l):Mo(l);if(u)for(const f in u)i[f]=u[f]}return i}else if(Ct(t)||_t(t))return t}const bd=/;(?![^(]*\))/g,yd=/:([^]+)/,xd=/\/\*[^]*?\*\//g;function wd(t){const i={};return t.replace(xd,"").split(bd).forEach(s=>{if(s){const l=s.split(yd);l.length>1&&(i[l[0].trim()]=l[1].trim())}}),i}function Ae(t){let i="";if(Ct(t))i=t;else if(De(t))for(let s=0;s<t.length;s++){const l=Ae(t[s]);l&&(i+=l+" ")}else if(_t(t))for(const s in t)t[s]&&(i+=s+" ");return i.trim()}const kd="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",Sd=Xr(kd);function Fu(t){return!!t||t===""}function Td(t,i){if(t.length!==i.length)return!1;let s=!0;for(let l=0;s&&l<t.length;l++)s=Ji(t[l],i[l]);return s}function Ji(t,i){if(t===i)return!0;let s=Ll(t),l=Ll(i);if(s||l)return s&&l?t.getTime()===i.getTime():!1;if(s=ti(t),l=ti(i),s||l)return t===i;if(s=De(t),l=De(i),s||l)return s&&l?Td(t,i):!1;if(s=_t(t),l=_t(i),s||l){if(!s||!l)return!1;const u=Object.keys(t).length,f=Object.keys(i).length;if(u!==f)return!1;for(const h in t){const _=t.hasOwnProperty(h),y=i.hasOwnProperty(h);if(_&&!y||!_&&y||!Ji(t[h],i[h]))return!1}}return String(t)===String(i)}function tl(t,i){return t.findIndex(s=>Ji(s,i))}const Ru=t=>!!(t&&t.__v_isRef===!0),w=t=>Ct(t)?t:t==null?"":De(t)||_t(t)&&(t.toString===Iu||!Ge(t.toString))?Ru(t)?w(t.value):JSON.stringify(t,Bu,2):String(t),Bu=(t,i)=>Ru(i)?Bu(t,i.value):ts(i)?{[`Map(${i.size})`]:[...i.entries()].reduce((s,[l,u],f)=>(s[wr(l,f)+" =>"]=u,s),{})}:ls(i)?{[`Set(${i.size})`]:[...i.values()].map(s=>wr(s))}:ti(i)?wr(i):_t(i)&&!De(i)&&!$u(i)?String(i):i,wr=(t,i="")=>{var s;return ti(t)?`Symbol(${(s=t.description)!=null?s:i})`:t};/**
|
||||
* @vue/reactivity v3.5.39
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/let Wt;class Pd{constructor(i=!1){this.detached=i,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this._warnOnRun=!0,this.__v_skip=!0,!i&&Wt&&(Wt.active?(this.parent=Wt,this.index=(Wt.scopes||(Wt.scopes=[])).push(this)-1):(this._active=!1,this._warnOnRun=!1))}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let i,s;if(this.scopes)for(i=0,s=this.scopes.length;i<s;i++)this.scopes[i].pause();for(i=0,s=this.effects.length;i<s;i++)this.effects[i].pause()}}resume(){if(this._active&&this._isPaused){this._isPaused=!1;let i,s;if(this.scopes)for(i=0,s=this.scopes.length;i<s;i++)this.scopes[i].resume();for(i=0,s=this.effects.length;i<s;i++)this.effects[i].resume()}}run(i){if(this._active){const s=Wt;try{return Wt=this,i()}finally{Wt=s}}}on(){++this._on===1&&(this.prevScope=Wt,Wt=this)}off(){if(this._on>0&&--this._on===0){if(Wt===this)Wt=this.prevScope;else{let i=Wt;for(;i;){if(i.prevScope===this){i.prevScope=this.prevScope;break}i=i.prevScope}}this.prevScope=void 0}}stop(i){if(this._active){this._active=!1;let s,l;for(s=0,l=this.effects.length;s<l;s++)this.effects[s].stop();for(this.effects.length=0,s=0,l=this.cleanups.length;s<l;s++)this.cleanups[s]();if(this.cleanups.length=0,this.scopes){for(s=0,l=this.scopes.length;s<l;s++)this.scopes[s].stop(!0);this.scopes.length=0}if(!this.detached&&this.parent&&!i){const u=this.parent.scopes.pop();u&&u!==this&&(this.parent.scopes[this.index]=u,u.index=this.index)}this.parent=void 0}}}function Cd(){return Wt}let St;const kr=new WeakSet;class Uu{constructor(i){this.fn=i,this.deps=void 0,this.depsTail=void 0,this.flags=5,this.next=void 0,this.cleanup=void 0,this.scheduler=void 0,Wt&&(Wt.active?Wt.effects.push(this):this.flags&=-2)}pause(){this.flags|=64}resume(){this.flags&64&&(this.flags&=-65,kr.has(this)&&(kr.delete(this),this.trigger()))}notify(){this.flags&2&&!(this.flags&32)||this.flags&8||Zu(this)}run(){if(!(this.flags&1))return this.fn();this.flags|=2,Ml(this),Hu(this);const i=St,s=ei;St=this,ei=!0;try{return this.fn()}finally{ju(this),St=i,ei=s,this.flags&=-3}}stop(){if(this.flags&1){for(let i=this.deps;i;i=i.nextDep)ol(i);this.deps=this.depsTail=void 0,Ml(this),this.onStop&&this.onStop(),this.flags&=-2}}trigger(){this.flags&64?kr.add(this):this.scheduler?this.scheduler():this.runIfDirty()}runIfDirty(){$r(this)&&this.run()}get dirty(){return $r(this)}}let Vu=0,Bs,Us;function Zu(t,i=!1){if(t.flags|=8,i){t.next=Us,Us=t;return}t.next=Bs,Bs=t}function nl(){Vu++}function il(){if(--Vu>0)return;if(Us){let i=Us;for(Us=void 0;i;){const s=i.next;i.next=void 0,i.flags&=-9,i=s}}let t;for(;Bs;){let i=Bs;for(Bs=void 0;i;){const s=i.next;if(i.next=void 0,i.flags&=-9,i.flags&1)try{i.trigger()}catch(l){t||(t=l)}i=s}}if(t)throw t}function Hu(t){for(let i=t.deps;i;i=i.nextDep)i.version=-1,i.prevActiveLink=i.dep.activeLink,i.dep.activeLink=i}function ju(t){let i,s=t.depsTail,l=s;for(;l;){const u=l.prevDep;l.version===-1?(l===s&&(s=u),ol(l),Ld(l)):i=l,l.dep.activeLink=l.prevActiveLink,l.prevActiveLink=void 0,l=u}t.deps=i,t.depsTail=s}function $r(t){for(let i=t.deps;i;i=i.nextDep)if(i.dep.version!==i.version||i.dep.computed&&(Wu(i.dep.computed)||i.dep.version!==i.version))return!0;return!!t._dirty}function Wu(t){if(t.flags&4&&!(t.flags&16)||(t.flags&=-17,t.globalVersion===Ws)||(t.globalVersion=Ws,!t.isSSR&&t.flags&128&&(!t.deps&&!t._dirty||!$r(t))))return;t.flags|=2;const i=t.dep,s=St,l=ei;St=t,ei=!0;try{Hu(t);const u=t.fn(t._value);(i.version===0||ci(u,t._value))&&(t.flags|=128,t._value=u,i.version++)}catch(u){throw i.version++,u}finally{St=s,ei=l,ju(t),t.flags&=-3}}function ol(t,i=!1){const{dep:s,prevSub:l,nextSub:u}=t;if(l&&(l.nextSub=u,t.prevSub=void 0),u&&(u.prevSub=l,t.nextSub=void 0),s.subs===t&&(s.subs=l,!l&&s.computed)){s.computed.flags&=-5;for(let f=s.computed.deps;f;f=f.nextDep)ol(f,!0)}!i&&!--s.sc&&s.map&&s.map.delete(s.key)}function Ld(t){const{prevDep:i,nextDep:s}=t;i&&(i.nextDep=s,t.prevDep=void 0),s&&(s.prevDep=i,t.nextDep=void 0)}let ei=!0;const Ku=[];function fi(){Ku.push(ei),ei=!1}function hi(){const t=Ku.pop();ei=t===void 0?!0:t}function Ml(t){const{cleanup:i}=t;if(t.cleanup=void 0,i){const s=St;St=void 0;try{i()}finally{St=s}}}let Ws=0;class Ad{constructor(i,s){this.sub=i,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class sl{constructor(i){this.computed=i,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(i){if(!St||!ei||St===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==St)s=this.activeLink=new Ad(St,this),St.deps?(s.prevDep=St.depsTail,St.depsTail.nextDep=s,St.depsTail=s):St.deps=St.depsTail=s,Gu(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const l=s.nextDep;l.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=l),s.prevDep=St.depsTail,s.nextDep=void 0,St.depsTail.nextDep=s,St.depsTail=s,St.deps===s&&(St.deps=l)}return s}trigger(i){this.versiLine truncated
|
||||
* @vue/runtime-core v3.5.39
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/function ta(t,i,s,l){try{return l?t(...l):t()}catch(u){Ja(u,i,s)}}function Wn(t,i,s,l){if(Ge(t)){const u=ta(t,i,s,l);return u&&zu(u)&&u.catch(f=>{Ja(f,i,s)}),u}if(De(t)){const u=[];for(let f=0;f<t.length;f++)u.push(Wn(t[f],i,s,l));return u}}function Ja(t,i,s,l=!0){const u=i?i.vnode:null,{errorHandler:f,throwUnhandledErrorInProduction:h}=i&&i.appContext.config||wt;if(i){let _=i.parent;const y=i.proxy,C=`https://vuejs.org/error-reference/#runtime-${s}`;for(;_;){const T=_.ec;if(T){for(let M=0;M<T.length;M++)if(T[M](t,y,C)===!1)return}_=_.parent}if(f){fi(),ta(f,null,10,[t,y,C]),hi();return}}ef(t,s,u,l,h)}function ef(t,i,s,l=!0,u=!1){if(u)throw t;console.error(t)}const fn=[];let ri=-1;const ns=[];let Yi=null,Qo=0;const nc=Promise.resolve();let Ia=null;function ic(t){const i=Ia||nc;return t?i.then(this?t.bind(this):t):i}function tf(t){let i=ri+1,s=fn.length;for(;i<s;){const l=i+s>>>1,u=fn[l],f=Gs(u);f<t||f===t&&u.flags&2?i=l+1:s=l}return i}function ul(t){if(!(t.flags&1)){const i=Gs(t),s=fn[fn.length-1];!s||!(t.flags&2)&&i>=Gs(s)?fn.push(t):fn.splice(tf(i),0,t),t.flags|=1,oc()}}function oc(){Ia||(Ia=nc.then(ac))}function nf(t){De(t)?ns.push(...t):Yi&&t.id===-1?Yi.splice(Qo+1,0,t):t.flags&1||(ns.push(t),t.flags|=1),oc()}function Ol(t,i,s=ri+1){for(;s<fn.length;s++){const l=fn[s];if(l&&l.flags&2){if(t&&l.id!==t.uid)continue;fn.splice(s,1),s--,l.flags&4&&(l.flags&=-2),l(),l.flags&4||(l.flags&=-2)}}}function sc(t){if(ns.length){const i=[...new Set(ns)].sort((s,l)=>Gs(s)-Gs(l));if(ns.length=0,Yi){Yi.push(...i);return}for(Yi=i,Qo=0;Qo<Yi.length;Qo++){const s=Yi[Qo];s.flags&4&&(s.flags&=-2),s.flags&8||s(),s.flags&=-2}Yi=null,Qo=0}}const Gs=t=>t.id==null?t.flags&2?-1:1/0:t.id;function ac(t){try{for(ri=0;ri<fn.length;ri++){const i=fn[ri];i&&!(i.flags&8)&&(i.flags&4&&(i.flags&=-2),ta(i,i.i,i.i?15:14),i.flags&4||(i.flags&=-2))}}finally{for(;ri<fn.length;ri++){const i=fn[ri];i&&(i.flags&=-2)}ri=-1,fn.length=0,sc(),Ia=null,(fn.length||ns.length)&&ac()}}let on=null,rc=null;function $a(t){const i=on;return on=t,rc=t&&t.type.__scopeId||null,i}function xe(t,i=on,s){if(!i||t._n)return t;const l=(...u)=>{l._d&&Fa(-1);const f=$a(i);let h;try{h=t(...u)}finally{$a(f),l._d&&Fa(1)}return h};return l._n=!0,l._c=!0,l._d=!0,l}function Q(t,i){if(on===null)return t;const s=nr(on),l=t.dirs||(t.dirs=[]);for(let u=0;u<i.length;u++){let[f,h,_,y=wt]=i[u];f&&(Ge(f)&&(f={mounted:f,updated:f}),f.deep&&Li(h),l.push({dir:f,instance:s,value:h,oldValue:void 0,arg:_,modifiers:y}))}return t}function xo(t,i,s,l){const u=t.dirs,f=i&&i.dirs;for(let h=0;h<u.length;h++){const _=u[h];f&&(_.oldValue=f[h].value);let y=_.dir[l];y&&(fi(),Wn(y,s,8,[t.el,_,t,i]),hi())}}function lc(t,i){if(hn){let s=hn.provides;const l=hn.parent&&hn.parent.provides;l===s&&(s=hn.provides=Object.create(l)),s[t]=i}}function Vs(t,i,s=!1){const l=Bc();if(l||os){let u=os?os._context.provides:l?l.parent==null||l.ce?l.vnode.appContext&&l.vnode.appContext.provides:l.parent.provides:void 0;if(u&&t in u)return u[t];if(arguments.length>1)return s&&Ge(i)?i.call(l&&l.proxy):i}}const of=Symbol.for("v-scx"),sf=()=>Vs(of);function Rt(t,i,s){return uc(t,i,s)}function uc(t,i,s=wt){const{immediate:l,deep:u,flush:f,once:h}=s,_=Ht({},s),y=i&&l||!i&&f!=="post";let C;if(Xs){if(f==="sync"){const V=sf();C=V.__watcherHandles||(V.__watcherHandles=[])}else if(!y){const V=()=>{};return V.stop=di,V.resume=di,V.pause=di,V}}const T=hn;_.call=(V,K,F)=>Wn(V,T,K,F);let M=!1;f==="post"?_.scheduler=V=>{dn(V,T&&T.suspense)}:f!=="sync"&&(M=!0,_.scheduler=(V,K)=>{K?V():ul(V)}),_.augmentJob=V=>{i&&(V.flags|=4),M&&(V.flags|=2,T&&(V.id=T.uid,V.i=T))};const U=Qd(t,i,_);return Xs&&(C?C.push(U):y&&U()),U}function af(t,i,s){const l=this.proxy,u=Ct(t)?t.includes(".")?cc(l,t):()=>l[t]:t.bind(l,l);let f;Ge(i)?f=i:(f=i.handler,s=i);const h=na(this),_=uc(u,f.bind(l),s);return h(),_}function cc(t,i){const s=i.split(".");return()=>{let l=t;for(let u=0;u<s.length&&l;u++)l=l[s[u]];return l}}const qi=new WeakMap,dc=Symbol("_vte"),fc=t=>t.__isTeleport,Po=t=>t&&(t.disabled||t.disabled===""),rf=t=>t&&(t.defer||t.defer===""),zl=t=>typeof SVGElement<"u"&&t instanceof SVGElement,Il=t=>typeof MathMLElement=="function"&&t instanceof MathMLElement,Br=(t,i)=>{const s=t&&t.to;return Ct(s)?i?i(s):null:s},lf={name:"Teleport",__isTeleport:!0,process(t,i,s,l,u,f,h,_,y,C){const{mc:T,pc:M,pbc:U,o:{insert:V,querySelector:K,createText:F,createComment:me,parentNode:he}}=C,Y=Po(i.props);let{dynamicChildren:Le}=i;const ce=(ze,We,we)=>{ze.shapeFlag&16&&T(ze.children,We,we,u,f,h,_,y)},Be=(ze=i)=>{const We=Po(ze.props),we=ze.target=Br(ze.props,K),le=Ur(we,ze,F,V);we&&(h!=="svg"&&zl(we)?h="svg":h!=="mathml"&&Il(we)&&(h="mathml"),u&&u.isCE&&(u.ce._teleportTargets||(u.ce._teleportTargets=new Set)).add(we),We||(ce(ze,we,le),$s(ze,!1)))},Ne=ze=>{const We=()=>{if(qi.get(ze)===We){if(qi.delete(ze),Po(ze.props)){const we=he(ze.el)||s;ce(ze,we,ze.anchor),$s(ze,!0)}Be(ze)}};qi.set(ze,We),dn(We,f)};if(t==null){const ze=i.el=F(""),We=i.anchor=F("");if(V(ze,s,l),V(We,s,l),rf(
Line truncated
|
||||
* @vue/runtime-dom v3.5.39
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/let Gr;const Gl=typeof window<"u"&&window.trustedTypes;if(Gl)try{Gr=Gl.createPolicy("vue",{createHTML:t=>t})}catch{}const Zc=Gr?t=>Gr.createHTML(t):t=>t,fh="http://www.w3.org/2000/svg",hh="http://www.w3.org/1998/Math/MathML",Ti=typeof document<"u"?document:null,ql=Ti&&Ti.createElement("template"),ph={insert:(t,i,s)=>{i.insertBefore(t,s||null)},remove:t=>{const i=t.parentNode;i&&i.removeChild(t)},createElement:(t,i,s,l)=>{const u=i==="svg"?Ti.createElementNS(fh,t):i==="mathml"?Ti.createElementNS(hh,t):s?Ti.createElement(t,{is:s}):Ti.createElement(t);return t==="select"&&l&&l.multiple!=null&&u.setAttribute("multiple",l.multiple),u},createText:t=>Ti.createTextNode(t),createComment:t=>Ti.createComment(t),setText:(t,i)=>{t.nodeValue=i},setElementText:(t,i)=>{t.textContent=i},parentNode:t=>t.parentNode,nextSibling:t=>t.nextSibling,querySelector:t=>Ti.querySelector(t),setScopeId(t,i){t.setAttribute(i,"")},insertStaticContent(t,i,s,l,u,f){const h=s?s.previousSibling:i.lastChild;if(u&&(u===f||u.nextSibling))for(;i.insertBefore(u.cloneNode(!0),s),!(u===f||!(u=u.nextSibling)););else{ql.innerHTML=Zc(l==="svg"?`<svg>${t}</svg>`:l==="mathml"?`<math>${t}</math>`:t);const _=ql.content;if(l==="svg"||l==="mathml"){const y=_.firstChild;for(;y.firstChild;)_.appendChild(y.firstChild);_.removeChild(y)}i.insertBefore(_,s)}return[h?h.nextSibling:i.firstChild,s?s.previousSibling:i.lastChild]}},Ki="transition",zs="animation",Qs=Symbol("_vtc"),Hc={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},mh=Ht({},hc,Hc),gh=t=>(t.displayName="Transition",t.props=mh,t),vh=gh((t,{slots:i})=>ch(hf,_h(t),i)),ko=(t,i=[])=>{De(t)?t.forEach(s=>s(...i)):t&&t(...i)},Yl=t=>t?De(t)?t.some(i=>i.length>1):t.length>1:!1;function _h(t){const i={};for(const ie in t)ie in Hc||(i[ie]=t[ie]);if(t.css===!1)return i;const{name:s="v",type:l,duration:u,enterFromClass:f=`${s}-enter-from`,enterActiveClass:h=`${s}-enter-active`,enterToClass:_=`${s}-enter-to`,appearFromClass:y=f,appearActiveClass:C=h,appearToClass:T=_,leaveFromClass:M=`${s}-leave-from`,leaveActiveClass:U=`${s}-leave-active`,leaveToClass:V=`${s}-leave-to`}=t,K=bh(u),F=K&&K[0],me=K&&K[1],{onBeforeEnter:he,onEnter:Y,onEnterCancelled:Le,onLeave:ce,onLeaveCancelled:Be,onBeforeAppear:Ne=he,onAppear:ze=Y,onAppearCancelled:We=Le}=i,we=(ie,Ke,re,qe)=>{ie._enterCancelled=qe,So(ie,Ke?T:_),So(ie,Ke?C:h),re&&re()},le=(ie,Ke)=>{ie._isLeaving=!1,So(ie,M),So(ie,V),So(ie,U),Ke&&Ke()},Me=ie=>(Ke,re)=>{const qe=ie?ze:Y,fe=()=>we(Ke,ie,re);ko(qe,[Ke,fe]),Jl(()=>{So(Ke,ie?y:f),Si(Ke,ie?T:_),Yl(qe)||Xl(Ke,l,F,fe)})};return Ht(i,{onBeforeEnter(ie){ko(he,[ie]),Si(ie,f),Si(ie,h)},onBeforeAppear(ie){ko(Ne,[ie]),Si(ie,y),Si(ie,C)},onEnter:Me(!1),onAppear:Me(!0),onLeave(ie,Ke){ie._isLeaving=!0;const re=()=>le(ie,Ke);Si(ie,M),ie._enterCancelled?(Si(ie,U),tu(ie)):(tu(ie),Si(ie,U)),Jl(()=>{ie._isLeaving&&(So(ie,M),Si(ie,V),Yl(ce)||Xl(ie,l,me,re))}),ko(ce,[ie,re])},onEnterCancelled(ie){we(ie,!1,void 0,!0),ko(Le,[ie])},onAppearCancelled(ie){we(ie,!0,void 0,!0),ko(We,[ie])},onLeaveCancelled(ie){le(ie),ko(Be,[ie])}})}function bh(t){if(t==null)return null;if(_t(t))return[Mr(t.enter),Mr(t.leave)];{const i=Mr(t);return[i,i]}}function Mr(t){return _d(t)}function Si(t,i){i.split(/\s+/).forEach(s=>s&&t.classList.add(s)),(t[Qs]||(t[Qs]=new Set)).add(i)}function So(t,i){i.split(/\s+/).forEach(l=>l&&t.classList.remove(l));const s=t[Qs];s&&(s.delete(i),s.size||(t[Qs]=void 0))}function Jl(t){requestAnimationFrame(()=>{requestAnimationFrame(t)})}let yh=0;function Xl(t,i,s,l){const u=t._endId=++yh,f=()=>{u===t._endId&&l()};if(s!=null)return setTimeout(f,s);const{type:h,timeout:_,propCount:y}=xh(t,i);if(!h)return l();const C=h+"end";let T=0;const M=()=>{t.removeEventListener(C,U),f()},U=V=>{V.target===t&&++T>=y&&M()};setTimeout(()=>{T<y&&M()},_+1),t.addEventListener(C,U)}function xh(t,i){const s=window.getComputedStyle(t),l=K=>(s[K]||"").split(", "),u=l(`${Ki}Delay`),f=l(`${Ki}Duration`),h=Ql(u,f),_=l(`${zs}Delay`),y=l(`${zs}Duration`),C=Ql(_,y);let T=null,M=0,U=0;i===Ki?h>0&&(T=Ki,M=h,U=f.length):i===zs?C>0&&(T=zs,M=C,U=y.length):(M=Math.max(h,C),T=M>0?h>C?Ki:zs:null,U=T?T===Ki?f.length:y.length:0);const V=T===Ki&&/\b(?:transform|all)(?:,|$)/.test(l(`${Ki}Property`).toString());return{type:T,timeout:M,propCount:U,hasTransform:V}}function Ql(t,i){for(;t.length<i.length;)t=t.concat(t);return Math.max(...i.map((s,l)=>eu(s)+eu(t[l])))}function eu(t){return t==="auto"?0:Number(t.slice(0,-1).replace(",","."))*1e3}function tu(t){return(t?t.ownerDocument:document).body.offsetHeight}function wh(t,i,s){const l=t[Qs];l&&(i=(i?[i,...l]:[...l]).join(" ")),i==null?t.removeAttribute("class"):s?t.setAttribute("class",i):t.className=i}const Ua=Symbol("_vod"),jc=Symbol("_vsh"),kh={name:"show",beforeMount(t,{value:i},{transition:s
Line truncated
|
||||
* Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
|
||||
* (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
|
||||
*/var lm=Fs.exports,Tu;function um(){return Tu||(Tu=1,(function(t,i){(function(s,l){l(i)})(lm,(function(s){var l="1.9.4";function u(e){var n,o,r,d;for(o=1,r=arguments.length;o<r;o++){d=arguments[o];for(n in d)e[n]=d[n]}return e}var f=Object.create||(function(){function e(){}return function(n){return e.prototype=n,new e}})();function h(e,n){var o=Array.prototype.slice;if(e.bind)return e.bind.apply(e,o.call(arguments,1));var r=o.call(arguments,2);return function(){return e.apply(n,r.length?r.concat(o.call(arguments)):arguments)}}var _=0;function y(e){return"_leaflet_id"in e||(e._leaflet_id=++_),e._leaflet_id}function C(e,n,o){var r,d,v,P;return P=function(){r=!1,d&&(v.apply(o,d),d=!1)},v=function(){r?d=arguments:(e.apply(o,arguments),setTimeout(P,n),r=!0)},v}function T(e,n,o){var r=n[1],d=n[0],v=r-d;return e===r&&o?e:((e-d)%v+v)%v+d}function M(){return!1}function U(e,n){if(n===!1)return e;var o=Math.pow(10,n===void 0?6:n);return Math.round(e*o)/o}function V(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function K(e){return V(e).split(/\s+/)}function F(e,n){Object.prototype.hasOwnProperty.call(e,"options")||(e.options=e.options?f(e.options):{});for(var o in n)e.options[o]=n[o];return e.options}function me(e,n,o){var r=[];for(var d in e)r.push(encodeURIComponent(o?d.toUpperCase():d)+"="+encodeURIComponent(e[d]));return(!n||n.indexOf("?")===-1?"?":"&")+r.join("&")}var he=/\{ *([\w_ -]+) *\}/g;function Y(e,n){return e.replace(he,function(o,r){var d=n[r];if(d===void 0)throw new Error("No value provided for variable "+o);return typeof d=="function"&&(d=d(n)),d})}var Le=Array.isArray||function(e){return Object.prototype.toString.call(e)==="[object Array]"};function ce(e,n){for(var o=0;o<e.length;o++)if(e[o]===n)return o;return-1}var Be="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";function Ne(e){return window["webkit"+e]||window["moz"+e]||window["ms"+e]}var ze=0;function We(e){var n=+new Date,o=Math.max(0,16-(n-ze));return ze=n+o,window.setTimeout(e,o)}var we=window.requestAnimationFrame||Ne("RequestAnimationFrame")||We,le=window.cancelAnimationFrame||Ne("CancelAnimationFrame")||Ne("CancelRequestAnimationFrame")||function(e){window.clearTimeout(e)};function Me(e,n,o){if(o&&we===We)e.call(n);else return we.call(window,h(e,n))}function ie(e){e&&le.call(window,e)}var Ke={__proto__:null,extend:u,create:f,bind:h,get lastId(){return _},stamp:y,throttle:C,wrapNum:T,falseFn:M,formatNum:U,trim:V,splitWords:K,setOptions:F,getParamString:me,template:Y,isArray:Le,indexOf:ce,emptyImageUrl:Be,requestFn:we,cancelFn:le,requestAnimFrame:Me,cancelAnimFrame:ie};function re(){}re.extend=function(e){var n=function(){F(this),this.initialize&&this.initialize.apply(this,arguments),this.callInitHooks()},o=n.__super__=this.prototype,r=f(o);r.constructor=n,n.prototype=r;for(var d in this)Object.prototype.hasOwnProperty.call(this,d)&&d!=="prototype"&&d!=="__super__"&&(n[d]=this[d]);return e.statics&&u(n,e.statics),e.includes&&(qe(e.includes),u.apply(null,[r].concat(e.includes))),u(r,e),delete r.statics,delete r.includes,r.options&&(r.options=o.options?f(o.options):{},u(r.options,e.options)),r._initHooks=[],r.callInitHooks=function(){if(!this._initHooksCalled){o.callInitHooks&&o.callInitHooks.call(this),this._initHooksCalled=!0;for(var v=0,P=r._initHooks.length;v<P;v++)r._initHooks[v].call(this)}},n},re.include=function(e){var n=this.prototype.options;return u(this.prototype,e),e.options&&(this.prototype.options=n,this.mergeOptions(e.options)),this},re.mergeOptions=function(e){return u(this.prototype.options,e),this},re.addInitHook=function(e){var n=Array.prototype.slice.call(arguments,1),o=typeof e=="function"?e:function(){this[e].apply(this,n)};return this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(o),this};function qe(e){if(!(typeof L>"u"||!L||!L.Mixin)){e=Le(e)?e:[e];for(var n=0;n<e.length;n++)e[n]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",new Error().stack)}}var fe={on:function(e,n,o){if(typeof e=="object")for(var r in e)this._on(r,e[r],n);else{e=K(e);for(var d=0,v=e.length;d<v;d++)this._on(e[d],n,o)}return this},off:function(e,n,o){if(!arguments.length)delete this._events;else if(typeof e=="object")for(var r in e)this._off(r,e[r],n);else{e=K(e);for(var d=arguments.length===1,v=0,P=e.length;v<P;v++)d?this._off(e[v]):this._off(e[v],n,o)}return this},_on:function(e,n,o,r){if(typeof n!="function"){console.warn("wrong listener type: "+typeof n);return}if(this._listens(e,n,o)===!1){o===this&&(o=void 0);var d={fn:n,ctx:o};r&&(d.once=!0),this._events=this._events||{},this._events[e]=this._events[e]||[],this._events[e].push(d)}},_off:function(e,n,o){var r,d,v;if(this._events&&(r=this._events[e],!!r)){if(arguments.length===1){if(this._firingCount)for(d=0,v=r.length;d<v;d++)r[d].fn=M;delete this._events[e];return}if(typeof n!="function"){console.warn("wrong listener type:Line truncated
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
:root,[data-theme=light]{--navy-950: #0B1730;--navy-900: #0F1E3D;--navy-800: #1B2E52;--navy-700: #26406E;--blue-50: #EAF1FE;--blue-100: #D6E3FD;--blue-200: #B4CDFA;--blue-300: #8FB4F6;--blue-400: #5B93F5;--blue-500: #3D7BF0;--blue-600: #2B62CC;--blue-700: #1F4CA0;--slate-0: #FFFFFF;--slate-50: #F6F7F9;--slate-100: #EEF0F3;--slate-150: #E6E9EE;--slate-200: #DCE0E7;--slate-300: #C5CCD7;--slate-400: #97A1B0;--slate-500: #6B7688;--slate-600: #4C5566;--slate-700: #333B4A;--slate-800: #1E2635;--slate-900: #131A28;--slate-950: #0B111C;--steel: #5A6B85;--green-500: #1F8A5B;--green-100: #DCF1E7;--green-600:#177049;--amber-500: #D9852B;--amber-100: #FBEBD5;--amber-600:#B86C1B;--red-500: #D64545;--red-100: #FBE0E0;--red-600: #B83232;--bg-app: var(--slate-100);--bg-subtle: var(--slate-50);--surface: var(--slate-0);--surface-2: var(--slate-50);--surface-inset: var(--slate-100);--border: var(--slate-200);--border-strong: var(--slate-300);--border-subtle: var(--slate-150);--text-primary: var(--navy-900);--text-secondary:var(--steel);--text-tertiary: var(--slate-400);--text-inverse: var(--slate-0);--text-on-accent:#FFFFFF;--accent: var(--blue-500);--accent-hover: var(--blue-600);--accent-active: var(--blue-700);--accent-soft: var(--blue-50);--accent-soft-fg:var(--blue-700);--focus-ring: color-mix(in srgb, var(--blue-500) 45%, transparent);--success: var(--green-500);--success-soft: var(--green-100);--success-fg: var(--green-600);--warning: var(--amber-500);--warning-soft: var(--amber-100);--warning-fg: var(--amber-600);--danger: var(--red-500);--danger-soft: var(--red-100);--danger-fg: var(--red-600);--overlay: color-mix(in srgb, var(--navy-950) 55%, transparent);--font-sans: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--font-mono: "Space Mono", ui-monospace, "SF Mono", "JetBrains Mono", monospace;--radius-xs: 4px;--radius-sm: 6px;--radius-md: 10px;--radius-lg: 14px;--radius-xl: 20px;--radius-pill: 999px;--shadow-xs: 0 1px 2px rgba(15,30,61,.06);--shadow-sm: 0 1px 2px rgba(15,30,61,.06), 0 1px 3px rgba(15,30,61,.04);--shadow-md: 0 2px 4px rgba(15,30,61,.06), 0 6px 16px rgba(15,30,61,.08);--shadow-lg: 0 8px 24px rgba(15,30,61,.1), 0 2px 6px rgba(15,30,61,.06);--ease-standard: cubic-bezier(.4, 0, .2, 1);--ease-out: cubic-bezier(.16, 1, .3, 1);--dur-fast: .12s;--dur-base: .2s;color-scheme:light}[data-theme=dark]{--bg-app: var(--navy-950);--bg-subtle: var(--slate-950);--surface: #10203F;--surface-2: #142748;--surface-inset: var(--navy-950);--border: color-mix(in srgb, #FFFFFF 10%, transparent);--border-strong: color-mix(in srgb, #FFFFFF 18%, transparent);--border-subtle: color-mix(in srgb, #FFFFFF 6%, transparent);--text-primary: #F4F7FC;--text-secondary:#8FA0BE;--text-tertiary: #5E6E8C;--text-inverse: var(--navy-900);--text-on-accent:#FFFFFF;--accent: var(--blue-400);--accent-hover: var(--blue-300);--accent-active: var(--blue-200);--accent-soft: color-mix(in srgb, var(--blue-500) 18%, transparent);--accent-soft-fg:var(--blue-300);--focus-ring: color-mix(in srgb, var(--blue-400) 55%, transparent);--success:var(--green-500);--success-soft: color-mix(in srgb, var(--green-500) 22%, transparent);--success-fg:#5FD3A0;--warning:var(--amber-500);--warning-soft: color-mix(in srgb, var(--amber-500) 22%, transparent);--warning-fg:#F0B26A;--danger: var(--red-500);--danger-soft: color-mix(in srgb, var(--red-500) 22%, transparent);--danger-fg: #F08A8A;--overlay: color-mix(in srgb, #000000 62%, transparent);--shadow-xs: 0 1px 2px rgba(0,0,0,.35);--shadow-sm: 0 1px 3px rgba(0,0,0,.4);--shadow-md: 0 4px 12px rgba(0,0,0,.45);--shadow-lg: 0 12px 32px rgba(0,0,0,.5);color-scheme:dark}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-Line truncated
|
||||
:root,[data-theme=light]{--navy-950: #0B1730;--navy-900: #0F1E3D;--navy-800: #1B2E52;--navy-700: #26406E;--blue-50: #EAF1FE;--blue-100: #D6E3FD;--blue-200: #B4CDFA;--blue-300: #8FB4F6;--blue-400: #5B93F5;--blue-500: #3D7BF0;--blue-600: #2B62CC;--blue-700: #1F4CA0;--slate-0: #FFFFFF;--slate-50: #F6F7F9;--slate-100: #EEF0F3;--slate-150: #E6E9EE;--slate-200: #DCE0E7;--slate-300: #C5CCD7;--slate-400: #97A1B0;--slate-500: #6B7688;--slate-600: #4C5566;--slate-700: #333B4A;--slate-800: #1E2635;--slate-900: #131A28;--slate-950: #0B111C;--steel: #5A6B85;--green-500: #1F8A5B;--green-100: #DCF1E7;--green-600:#177049;--amber-500: #D9852B;--amber-100: #FBEBD5;--amber-600:#B86C1B;--red-500: #D64545;--red-100: #FBE0E0;--red-600: #B83232;--bg-app: var(--slate-100);--bg-subtle: var(--slate-50);--surface: var(--slate-0);--surface-2: var(--slate-50);--surface-inset: var(--slate-100);--border: var(--slate-200);--border-strong: var(--slate-300);--border-subtle: var(--slate-150);--text-primary: var(--navy-900);--text-secondary:var(--steel);--text-tertiary: var(--slate-400);--text-inverse: var(--slate-0);--text-on-accent:#FFFFFF;--accent: var(--blue-500);--accent-hover: var(--blue-600);--accent-active: var(--blue-700);--accent-soft: var(--blue-50);--accent-soft-fg:var(--blue-700);--focus-ring: color-mix(in srgb, var(--blue-500) 45%, transparent);--success: var(--green-500);--success-soft: var(--green-100);--success-fg: var(--green-600);--warning: var(--amber-500);--warning-soft: var(--amber-100);--warning-fg: var(--amber-600);--danger: var(--red-500);--danger-soft: var(--red-100);--danger-fg: var(--red-600);--overlay: color-mix(in srgb, var(--navy-950) 55%, transparent);--font-sans: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--font-mono: "Space Mono", ui-monospace, "SF Mono", "JetBrains Mono", monospace;--radius-xs: 4px;--radius-sm: 6px;--radius-md: 10px;--radius-lg: 14px;--radius-xl: 20px;--radius-pill: 999px;--shadow-xs: 0 1px 2px rgba(15,30,61,.06);--shadow-sm: 0 1px 2px rgba(15,30,61,.06), 0 1px 3px rgba(15,30,61,.04);--shadow-md: 0 2px 4px rgba(15,30,61,.06), 0 6px 16px rgba(15,30,61,.08);--shadow-lg: 0 8px 24px rgba(15,30,61,.1), 0 2px 6px rgba(15,30,61,.06);--ease-standard: cubic-bezier(.4, 0, .2, 1);--ease-out: cubic-bezier(.16, 1, .3, 1);--dur-fast: .12s;--dur-base: .2s;color-scheme:light}[data-theme=dark]{--bg-app: var(--navy-950);--bg-subtle: var(--slate-950);--surface: #10203F;--surface-2: #142748;--surface-inset: var(--navy-950);--border: color-mix(in srgb, #FFFFFF 10%, transparent);--border-strong: color-mix(in srgb, #FFFFFF 18%, transparent);--border-subtle: color-mix(in srgb, #FFFFFF 6%, transparent);--text-primary: #F4F7FC;--text-secondary:#8FA0BE;--text-tertiary: #5E6E8C;--text-inverse: var(--navy-900);--text-on-accent:#FFFFFF;--accent: var(--blue-400);--accent-hover: var(--blue-300);--accent-active: var(--blue-200);--accent-soft: color-mix(in srgb, var(--blue-500) 18%, transparent);--accent-soft-fg:var(--blue-300);--focus-ring: color-mix(in srgb, var(--blue-400) 55%, transparent);--success:var(--green-500);--success-soft: color-mix(in srgb, var(--green-500) 22%, transparent);--success-fg:#5FD3A0;--warning:var(--amber-500);--warning-soft: color-mix(in srgb, var(--amber-500) 22%, transparent);--warning-fg:#F0B26A;--danger: var(--red-500);--danger-soft: color-mix(in srgb, var(--red-500) 22%, transparent);--danger-fg: #F08A8A;--overlay: color-mix(in srgb, #000000 62%, transparent);--shadow-xs: 0 1px 2px rgba(0,0,0,.35);--shadow-sm: 0 1px 3px rgba(0,0,0,.4);--shadow-md: 0 4px 12px rgba(0,0,0,.45);--shadow-lg: 0 12px 32px rgba(0,0,0,.5);color-scheme:dark}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-Line truncated
|
||||
Vendored
+2
-2
@@ -35,8 +35,8 @@
|
||||
})()
|
||||
</script>
|
||||
<title>PilotVault — Control Panel</title>
|
||||
<script type="module" crossorigin src="./assets/index-B-DwId4e.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-Dr5W1RO_.css">
|
||||
<script type="module" crossorigin src="./assets/index-DWe3LEIB.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-buxVzOVb.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -66,6 +66,7 @@ func main() {
|
||||
mux.HandleFunc("GET /bff/integrations/openweather", app.requireAuth(app.handleGetOpenWeather))
|
||||
mux.HandleFunc("PUT /bff/integrations/openweather", app.requireAuth(app.handlePutOpenWeather))
|
||||
mux.HandleFunc("POST /bff/integrations/openweather/health", app.requireAuth(app.handleOpenWeatherHealth))
|
||||
mux.HandleFunc("GET /bff/integrations/openweather/current", app.requireAuth(app.handleOpenWeatherCurrent))
|
||||
// User-management (role + org scoping enforced by the API Server)
|
||||
mux.HandleFunc("GET /bff/users", app.requireAuth(app.handleListUsers))
|
||||
mux.HandleFunc("POST /bff/users", app.requireAuth(app.handleCreateUser))
|
||||
|
||||
@@ -310,6 +310,20 @@ export async function testOpenWeather() {
|
||||
return { ok: r.ok, status: r.status, body: await r.json().catch(() => ({})) }
|
||||
}
|
||||
|
||||
// Current conditions for the Overview weather card. lat/lon optionally override the
|
||||
// configured location (drone/device/browser point). Returns {weather, units} when
|
||||
// available, or {unavailable:true, detail} when OpenWeather is off for the caller.
|
||||
export async function getOpenWeatherCurrent(lat, lon) {
|
||||
try {
|
||||
const qs = lat != null && lon != null ? `?lat=${encodeURIComponent(lat)}&lon=${encodeURIComponent(lon)}` : ''
|
||||
const r = await fetch(`/bff/integrations/openweather/current${qs}`)
|
||||
if (!r.ok) return { unavailable: true, detail: 'Weather unavailable' }
|
||||
return await r.json()
|
||||
} catch {
|
||||
return { unavailable: true, detail: 'Weather unavailable' }
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- Logbook: drones ---------- */
|
||||
|
||||
export async function getDrones() {
|
||||
|
||||
@@ -7,7 +7,7 @@ import Settings from './Settings.vue'
|
||||
import Logbook from './Logbook.vue'
|
||||
import Documents from './Documents.vue'
|
||||
import Toggle from './settings/Toggle.vue'
|
||||
import { getDevices, sendCommand, getOpenSkyStates } from '../api.js'
|
||||
import { getDevices, sendCommand, getOpenSkyStates, getOpenWeatherCurrent } from '../api.js'
|
||||
import { formatTime, prefs } from '../prefs.js'
|
||||
import { countryForPoint, bboxForCountry } from '../countries.js'
|
||||
|
||||
@@ -144,6 +144,94 @@ function stopAirspace() {
|
||||
airTimer = null
|
||||
}
|
||||
|
||||
/* ---------- OpenWeather current conditions (Overview weather card) ---------- */
|
||||
// { loaded, unavailable, detail, data: owWeather|null, units, source, updatedAt }
|
||||
const weather = reactive({ loaded: false, unavailable: false, detail: '', data: null, units: 'metric', source: '', updatedAt: 0 })
|
||||
let weatherTimer = null
|
||||
// Weather changes slowly and OpenWeather refreshes roughly every 10 min upstream,
|
||||
// so poll gently to respect the API quota.
|
||||
const WEATHER_INTERVAL_MS = 10 * 60 * 1000
|
||||
|
||||
// Resolve the point to fetch weather for, reusing the map's location cascade but
|
||||
// as a single lat/lng: drone GPS → phone GPS → already-granted browser geolocation.
|
||||
// Returns null when none is known, so the server uses its configured default. Does
|
||||
// not prompt for geolocation itself (only reuses a point the map already obtained).
|
||||
function resolveWeatherPoint() {
|
||||
const drone =
|
||||
devicePoint(sel.value, 'latitude', 'longitude') ||
|
||||
ids.value.map((id) => devicePoint(devices[id], 'latitude', 'longitude')).find(Boolean)
|
||||
if (drone) return { lat: drone.lat, lng: drone.lng, source: 'drone' }
|
||||
const phone =
|
||||
devicePoint(sel.value, 'phoneLatitude', 'phoneLongitude') ||
|
||||
ids.value.map((id) => devicePoint(devices[id], 'phoneLatitude', 'phoneLongitude')).find(Boolean)
|
||||
if (phone) return { lat: phone.lat, lng: phone.lng, source: 'phone' }
|
||||
if (browserGeo.value) return { lat: browserGeo.value.lat, lng: browserGeo.value.lng, source: 'browser' }
|
||||
return null
|
||||
}
|
||||
|
||||
async function refreshWeather() {
|
||||
const p = resolveWeatherPoint()
|
||||
const res = await getOpenWeatherCurrent(p ? p.lat : undefined, p ? p.lng : undefined)
|
||||
weather.loaded = true
|
||||
weather.units = res.units || 'metric'
|
||||
if (res.unavailable || !res.weather) {
|
||||
weather.unavailable = true
|
||||
weather.detail = res.detail || 'Weather is unavailable.'
|
||||
weather.data = null
|
||||
return
|
||||
}
|
||||
weather.unavailable = false
|
||||
weather.detail = ''
|
||||
weather.data = res.weather
|
||||
weather.source = p ? p.source : 'default'
|
||||
weather.updatedAt = Date.now()
|
||||
}
|
||||
|
||||
function scheduleWeather() {
|
||||
if (weatherTimer) clearInterval(weatherTimer)
|
||||
weatherTimer = setInterval(() => {
|
||||
if (active.value === 'Overview') refreshWeather()
|
||||
}, WEATHER_INTERVAL_MS)
|
||||
}
|
||||
function startWeather() {
|
||||
refreshWeather()
|
||||
scheduleWeather()
|
||||
}
|
||||
function stopWeather() {
|
||||
if (weatherTimer) clearInterval(weatherTimer)
|
||||
weatherTimer = null
|
||||
}
|
||||
|
||||
// Temperature/wind units follow the resolved OpenWeather "units" setting.
|
||||
const tempUnit = computed(() => (weather.units === 'imperial' ? '°F' : weather.units === 'standard' ? 'K' : '°C'))
|
||||
const windUnit = computed(() => (weather.units === 'imperial' ? 'mph' : 'm/s'))
|
||||
|
||||
// Map an OpenWeather icon code (e.g. "01d", "10n") to an emoji, so the card needs
|
||||
// no external image and works offline.
|
||||
function wxEmoji(icon) {
|
||||
const c = (icon || '').slice(0, 2)
|
||||
if (c === '01') return (icon || '').endsWith('n') ? '🌙' : '☀️'
|
||||
return { '02': '🌤️', '03': '⛅', '04': '☁️', '09': '🌧️', '10': '🌦️', '11': '⛈️', '13': '❄️', '50': '🌫️' }[c] || '🌡️'
|
||||
}
|
||||
const weatherEmoji = computed(() => wxEmoji(weather.data && weather.data.icon))
|
||||
const weatherLocation = computed(() => {
|
||||
const d = weather.data
|
||||
if (!d) return ''
|
||||
return d.country ? `${d.location}, ${d.country}` : d.location || 'Unknown location'
|
||||
})
|
||||
const weatherSourceLabel = computed(() => {
|
||||
if (weather.source === 'drone') return 'at aircraft location'
|
||||
if (weather.source === 'phone' || weather.source === 'browser') return 'at your location'
|
||||
return 'default location'
|
||||
})
|
||||
const weatherUpdated = computed(() =>
|
||||
weather.updatedAt ? new Date(weather.updatedAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : '',
|
||||
)
|
||||
// Round a nullable numeric field for display, or "—" when absent.
|
||||
function wxNum(v, digits = 0) {
|
||||
return typeof v === 'number' ? v.toFixed(digits) : '—'
|
||||
}
|
||||
|
||||
const active = ref('Overview')
|
||||
const NAV = [
|
||||
['grid', 'Overview'],
|
||||
@@ -371,7 +459,10 @@ function track(id) {
|
||||
// Re-fetch air traffic immediately when the operator returns to the Overview tab,
|
||||
// so the map isn't stale for up to a poll interval.
|
||||
watch(active, (v) => {
|
||||
if (v === 'Overview') refreshAirspace()
|
||||
if (v === 'Overview') {
|
||||
refreshAirspace()
|
||||
refreshWeather()
|
||||
}
|
||||
})
|
||||
|
||||
// React to the "Show live air traffic" map toggle: fetch at once when enabled,
|
||||
@@ -392,12 +483,14 @@ onMounted(async () => {
|
||||
;(await getDevices()).forEach(upsert)
|
||||
connect()
|
||||
startAirspace()
|
||||
startWeather()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
stopped = true
|
||||
if (retry) clearTimeout(retry)
|
||||
if (ws) ws.close()
|
||||
stopAirspace()
|
||||
stopWeather()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -579,6 +672,68 @@ onBeforeUnmount(() => {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-5">
|
||||
<!-- weather -->
|
||||
<div class="panel p-5">
|
||||
<div class="mb-3.5 flex items-center justify-between">
|
||||
<div>
|
||||
<div class="eyebrow">Conditions</div>
|
||||
<div class="mt-0.5 text-base font-semibold text-ink">Weather</div>
|
||||
</div>
|
||||
<Icon name="sun" :size="16" class="text-ink-muted" />
|
||||
</div>
|
||||
|
||||
<!-- current conditions -->
|
||||
<template v-if="weather.data">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="text-5xl leading-none">{{ weatherEmoji }}</div>
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-baseline gap-1">
|
||||
<span class="text-[34px] font-bold leading-none tracking-tightest text-ink">{{ wxNum(weather.data.temp) }}</span>
|
||||
<span class="text-lg font-semibold text-ink-secondary">{{ tempUnit }}</span>
|
||||
</div>
|
||||
<div class="mt-1 truncate text-sm capitalize text-ink-secondary">{{ weather.data.description || '—' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-1.5 truncate text-xs text-ink-muted">{{ weatherLocation }} · {{ weatherSourceLabel }}</div>
|
||||
|
||||
<div class="mt-4 grid grid-cols-2 gap-2.5">
|
||||
<div class="rounded-lg bg-surface-2 px-3 py-2">
|
||||
<div class="eyebrow">Feels like</div>
|
||||
<div class="mt-0.5 font-mono text-sm text-ink">{{ wxNum(weather.data.feelsLike) }}{{ tempUnit }}</div>
|
||||
</div>
|
||||
<div class="rounded-lg bg-surface-2 px-3 py-2">
|
||||
<div class="eyebrow">Wind</div>
|
||||
<div class="mt-0.5 font-mono text-sm text-ink">{{ wxNum(weather.data.windSpeed, 1) }} {{ windUnit }}</div>
|
||||
</div>
|
||||
<div class="rounded-lg bg-surface-2 px-3 py-2">
|
||||
<div class="eyebrow">Humidity</div>
|
||||
<div class="mt-0.5 font-mono text-sm text-ink">{{ wxNum(weather.data.humidity) }}<span v-if="weather.data.humidity != null">%</span></div>
|
||||
</div>
|
||||
<div class="rounded-lg bg-surface-2 px-3 py-2">
|
||||
<div class="eyebrow">Cloud cover</div>
|
||||
<div class="mt-0.5 font-mono text-sm text-ink">{{ wxNum(weather.data.clouds) }}<span v-if="weather.data.clouds != null">%</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="weatherUpdated" class="mt-3 text-[11px] text-ink-muted">Updated {{ weatherUpdated }} · OpenWeather</div>
|
||||
</template>
|
||||
|
||||
<!-- unavailable (off / not enabled / no key) -->
|
||||
<div v-else-if="weather.loaded && weather.unavailable" class="grid place-items-center py-8 text-center">
|
||||
<Icon name="sun" :size="24" class="text-ink-muted" />
|
||||
<div class="mt-2 text-sm font-medium text-ink-secondary">Weather unavailable</div>
|
||||
<div class="mt-0.5 text-xs text-ink-muted">{{ weather.detail }}</div>
|
||||
</div>
|
||||
|
||||
<!-- loading -->
|
||||
<div v-else class="grid place-items-center py-8 text-center text-sm text-ink-muted">
|
||||
Loading weather…
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- schedule -->
|
||||
<div class="panel p-5">
|
||||
<div class="mb-3.5 flex items-center justify-between">
|
||||
<div>
|
||||
@@ -593,6 +748,7 @@ onBeforeUnmount(() => {
|
||||
<div class="mt-0.5 text-xs text-ink-muted">Scheduling is not wired to a backend yet.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- fleet table -->
|
||||
|
||||
Reference in new issue
Block a user