diff --git a/.gitignore b/.gitignore index 37c2314..1a6e609 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,37 @@ log/** release/* src/db/wgdashboard.db .jshintrc -node_modules/ \ No newline at end of file +node_modules/** +*/proxy.js +src/static/app/proxy.js + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo +.vite/* \ No newline at end of file diff --git a/README.md b/README.md index 1fe2a44..21bc86a 100644 --- a/README.md +++ b/README.md @@ -21,125 +21,272 @@ Hi Everyone, I've decided to promote the long time working `v3.1` to `v4`! This
- +
- + + + +
++
-Monitoring WireGuard is not convinient, need to login into server and type wg show
. That's why this platform is being created, to view all configurations and manage them in a easier way.
Note: This project is not affiliate to the official WireGuard Project ;)
+Monitoring WireGuard is not convenient, need to remote access to server and type wg show
. That's why this project is being created, to view all configurations and manage them in a easy way.
With all these awesome features, while keeping it simple, easy to install and use
-## 📣 What's New: v3.0 +This project is not affiliate to the official WireGuard Project
-- 🎉 **New Features** - - **Moved from TinyDB to SQLite**: SQLite provide a better performance and loading speed when getting peers! Also avoided crashing the database due to **race condition**. - - **Added Gunicorn WSGI Server**: This could provide more stable on handling HTTP request, and more flexibility in the future (such as HTTPS support). **BIG THANKS to @pgalonza :heart:** - - **Add Peers by Bulk:** User can add peers by bulk, just simply set the amount and click add. - - **Delete Peers by Bulk**: User can delete peers by bulk, without deleting peers one by one. - - **Download Peers in Zip**: User can download all *downloadable* peers in a zip. - - **Added Pre-shared Key to peers:** Now each peer can add with a pre-shared key to enhance security. Previously added peers can add the pre-shared key through the peer setting button. - - **Redirect Back to Previous Page:** The dashboard will now redirect you back to your previous page if the current session got timed out and you need to sign in again. - - **Added Some [🥘 Experimental Functions](#-experimental-functions)** - -- 🪚 **Bug Fixed** - - [IP Sorting range issues #99](https://github.com/donaldzou/WGDashboard/issues/99) [❤️ @barryboom] - - [INvalid character written to tunnel json file #108](https://github.com/donaldzou/WGDashboard/issues/108) [❤️ @ikidd] - - [Add IPv6 #91](https://github.com/donaldzou/WGDashboard/pull/91) [❤️ @pgalonza] - - [Added MTU and PersistentKeepalive to QR code and download files #112](https://github.com/donaldzou/WGDashboard/pull/112) [:heart: @reafian] - - **And many other bugs provided by our beloved users** :heart: -- **🧐 Other Changes** - - **Key generating moved to front-end**: No longer need to use the server's WireGuard to generate keys, thanks to the `wireguard.js` from the [official repository](https://git.zx2c4.com/wireguard-tools/tree/contrib/keygen-html/wireguard.js)! - - **Peer transfer calculation**: each peer will now show all transfer amount (previously was only showing transfer amount from the last configuration start-up). - - **UI adjustment on running peers**: peers will have a new style indicating that it is running. - - **`wgd.sh` finally can update itself**: So now user could update the whole dashboard from `wgd.sh`, with the `update` command. - - **Minified JS and CSS files**: Although only a small changes on the file size, but I think is still a good practice to save a bit of bandwidth ;) +## 📣 What's New: v4.0 -*And many other small changes for performance and bug fixes! :laughing:* +### 🎉 New Features -> If you have any other brilliant ideas for this project, please shout it in here [#129](https://github.com/donaldzou/WGDashboard/issues/129) :heart: +- **Updated dashboard design**: Re-designed some of the section with more modern style and layout, the UI is faster and more responsive, it also uses less memory. But overall is still the same dashboard you're familiarized. +- **Docker Solution**: We now have 2 docker solutions! Thanks to @DaanSelen & @shuricksumy for providing them. For more information, please see the [Docker](#-docker-solutions) section below. +- **Peer Job Scheduler**: Now you can schedule jobs for each peer to either **restrict** or **delete** the peer if the peer's total / upload / download data usage exceeded a limit, or you can set a specific datetime to restrict or delete the peer. +- **Share Peer's QR Code with Public Link**: You can share a peer's QR code and `.conf` file without the need to loging in. +- **WGDashboard's REST API**: You can now request all the api endpoint used in the dashboard. For more details please review the [API Documentation](./docs/api-documents.md). +- **Logging**: Dashboard will now log all activity on the dashboard and API requests. +- **Time-Based One-Time Password (TOTP)**: You can enable this function to add one more layer of security, and generate the TOTP with your choice of authenticator. +- **Designs** + - **Real-time Graphs**: You can view real-time data changes with graphs in each configuration. + - **Night mode**: You know what that means, it avoids bugs ;) +- **Enforce Python Virtual Environment**: I noticed newer Python version (3.12) does not allow to install packages globally, and plus I think is a good idea to use venv. + +### 🧐 Other Changes +- **Deprecated jQuery from the project, and migrated and rewrote the whole front-end with Vue.js. This allows the dashboard is future proofed, and potential cross server access with a desktop app.** +- Rewrote the backend into a REST API structure +- Improved SQL query efficient +- Removed all templates, except for `index.html` where it will load the Vue.js app. +- Parsing names in `.conf` +- Minimized the need to read `.conf`, only when any `.conf` is modified -**For users who is using `v2.x.x` please be sure to read [this](#please-note-for-user-who-is-using-v231-or-below) before updating WGDashboard ;)** +### 🥘 New Experimental Features + - **Cross-Server Access**: Now you can access other servers that installed `v4` of WGDashboard through API key. + - **Desktop App**: Thanks to **Cross-Server Access**, you can now download an ElectronJS based desktop app of WGDashboard, and use that to access WGDashboard on different servers. + - > For more information, please scroll down to [🥘 Experimental Functions](#-experimental-functions) + +> I can't thank enough for all of you who wait for this release, and for those who are new to this project, welcome :) +> Also, huge thanks to who contributed to this major release: +> @bolgovrussia, @eduardorosabales, @Profik, @airgapper, @tokon2000, @bkeenke, @kontorskiy777, @bugsse, @Johnnykson, @DaanSelen, @shuricksumy and many others!antonioag95 ⚠️ 💻 |
- tonjo 💻 |
- Richard Newton 💻 |
- David Long 💻 |
- Markus Neubauer 💻 |
-
/
at the end of your path. e.g /etc/wireguard
"})])]),h("div",P3,[M3,h("div",T3,[$e(c,{targetData:"username",title:"Username"}),D3,$e(u,{targetData:"password"}),this.dashboardConfigurationStore.getActiveCrossServer()?re("",!0):(D(),F("hr",O3)),this.dashboardConfigurationStore.getActiveCrossServer()?re("",!0):(D(),Ne(d,{key:1}))])]),$e(f)])])}const R3=ze(b3,[["render",I3]]),L3={name:"setup",components:{},setup(){return{store:et()}},data(){return{setup:{username:"",newPassword:"",repeatNewPassword:"",enable_totp:!0},loading:!1,errorMessage:"",done:!1}},computed:{goodToSubmit(){return this.setup.username&&this.setup.newPassword.length>=8&&this.setup.repeatNewPassword.length>=8&&this.setup.newPassword===this.setup.repeatNewPassword}},methods:{submit(){this.loading=!0,ft("/api/Welcome_Finish",this.setup,e=>{e.status?(this.done=!0,this.$router.push("/2FASetup")):(document.querySelectorAll("#createAccount input").forEach(t=>t.classList.add("is-invalid")),this.errorMessage=e.message,document.querySelector(".login-container-fluid").scrollTo({top:0,left:0,behavior:"smooth"})),this.loading=!1})}}},N3=["data-bs-theme"],F3={class:"m-auto text-body",style:{width:"500px"}},B3=h("span",{class:"dashboardLogo display-4"},"Nice to meet you!",-1),V3=h("p",{class:"mb-5"},"Please fill in the following fields to finish setup 😊",-1),H3=h("h3",null,"Create an account",-1),j3={key:0,class:"alert alert-danger"},W3={class:"d-flex flex-column gap-3"},z3={id:"createAccount",class:"d-flex flex-column gap-2"},Y3={class:"form-group text-body"},U3=h("label",{for:"username",class:"mb-1 text-muted"},[h("small",null,"Pick an username you like")],-1),K3={class:"form-group text-body"},q3=h("label",{for:"password",class:"mb-1 text-muted"},[h("small",null,"Create a password (at least 8 characters)")],-1),G3={class:"form-group text-body"},J3=h("label",{for:"confirmPassword",class:"mb-1 text-muted"},[h("small",null,"Confirm password")],-1),X3=["disabled"],Q3={key:0,class:"d-flex align-items-center w-100"},Z3=h("i",{class:"bi bi-chevron-right ms-auto"},null,-1),eN={key:1,class:"d-flex align-items-center w-100"},tN=h("span",{class:"spinner-border ms-auto spinner-border-sm",role:"status"},[h("span",{class:"visually-hidden"},"Loading...")],-1);function nN(e,t,n,s,i,o){return D(),F("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[h("div",F3,[B3,V3,h("div",null,[H3,this.errorMessage?(D(),F("div",j3,_e(this.errorMessage),1)):re("",!0),h("div",W3,[h("div",z3,[h("div",Y3,[U3,Re(h("input",{type:"text","onUpdate:modelValue":t[0]||(t[0]=r=>this.setup.username=r),class:"form-control",id:"username",name:"username",placeholder:"Maybe something like 'wiredragon'?",required:""},null,512),[[We,this.setup.username]])]),h("div",K3,[q3,Re(h("input",{type:"password","onUpdate:modelValue":t[1]||(t[1]=r=>this.setup.newPassword=r),class:"form-control",id:"password",name:"password",placeholder:"Make sure is strong enough",required:""},null,512),[[We,this.setup.newPassword]])]),h("div",G3,[J3,Re(h("input",{type:"password","onUpdate:modelValue":t[2]||(t[2]=r=>this.setup.repeatNewPassword=r),class:"form-control",id:"confirmPassword",name:"confirmPassword",placeholder:"and you can remember it :)",required:""},null,512),[[We,this.setup.repeatNewPassword]])])]),h("button",{class:"btn btn-dark btn-lg mb-5 d-flex btn-brand shadow align-items-center",ref:"signInBtn",disabled:!this.goodToSubmit||this.loading||this.done,onClick:t[3]||(t[3]=r=>this.submit())},[!this.loading&&!this.done?(D(),F("span",Q3,[ye(" Next"),Z3])):(D(),F("span",eN,[ye(" Saving..."),tN]))],8,X3)])])])],8,N3)}const sN=ze(L3,[["render",nN]]);function jf(e){return e.includes(":")?6:e.includes(".")?4:0}function iN(e){const t=jf(e);if(!t)throw new Error(`Invalid IP address: ${e}`);let n=0n,s=0n;const i=Object.create(null);if(t===4)for(const o of e.split(".").map(BigInt).reverse())n+=o*2n**s,s+=8n;else{if(e.includes(".")&&(i.ipv4mapped=!0,e=e.split(":").map(a=>{if(a.includes(".")){const[l,c,u,d]=a.split(".").map(f=>Number(f).toString(16).padStart(2,"0"));return`${l}${c}:${u}${d}`}else return a}).join(":")),e.includes("%")){let a;[,e,a]=/(.+)%(.+)/.exec(e),i.scopeid=a}const o=e.split(":"),r=o.indexOf("");if(r!==-1)for(;o.length<8;)o.splice(r,0,"");for(const a of o.map(l=>BigInt(parseInt(l||0,16))).reverse())n+=a*2n**s,s+=16n}return i.number=n,i.version=t,i}const Vg={4:32,6:128},oN=e=>e.includes("/")?jf(e):0;function rN(e){const t=oN(e),n=Object.create(null);if(n.single=!1,t)n.cidr=e,n.version=t;else{const d=jf(e);if(d)n.cidr=`${e}/${Vg[d]}`,n.version=d,n.single=!0;else throw new Error(`Network is not a CIDR or IP: ${e}`)}const[s,i]=n.cidr.split("/");n.prefix=i;const{number:o,version:r}=iN(s),a=Vg[r],l=o.toString(2).padStart(a,"0"),c=Number(a-i),u=l.substring(0,a-c);return n.start=BigInt(`0b${u}${"0".repeat(c)}`),n.end=BigInt(`0b${u}${"1".repeat(c)}`),n}/*! SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2015-2020 Jason A. Donenfeld 0&&e.stroke()}}function Js(e,t,n){return n=n||.5,!t||e&&e.x>t.left-n&&e.x l(i,A,w)&&a(i,A)!==0,k=()=>a(o,w)===0||l(o,A,w),y=()=>_||T(),x=()=>!_||k();for(let C=u,P=u;C<=d;++C)$=t[C%r],!$.skip&&(w=c($[s]),w!==A&&(_=l(w,i,o),b===null&&y()&&(b=a(w,i)===0?C:P),b!==null&&x()&&(g.push(a_({start:b,end:C,loop:f,count:r,style:p})),b=null),P=C,A=w));return b!==null&&g.push(a_({start:b,end:d,loop:f,count:r,style:p})),g}function G0(e,t){const n=[],s=e.segments;for(let i=0;i
+ By adding peers by bulk, each peer's name will be auto generated, and Allowed IP will be assign to the next available IP.
+ {{Peer.id}} {{Peer.allowed_ip}}1?2-l:l,l=this._easing(Math.min(1,Math.max(0,l))),this._target[i]=this._fn(o,a,l)}wait(){const t=this._promises||(this._promises=[]);return new Promise((n,s)=>{t.push({res:n,rej:s})})}_notify(t){const n=t?"res":"rej",s=this._promises||[];for(let i=0;ic.box.fullSize),!0),s=sa(na(t,"left"),!0),i=sa(na(t,"right")),o=sa(na(t,"top"),!0),r=sa(na(t,"bottom")),a=w_(t,"x"),l=w_(t,"y");return{fullSize:n,leftAndTop:s.concat(o),rightAndBottom:i.concat(l).concat(r).concat(a),chartArea:na(t,"chartArea"),vertical:s.concat(i).concat(l),horizontal:o.concat(r).concat(a)}}function x_(e,t,n,s){return Math.max(e[n],t[n])+Math.max(e[s],t[s])}function e1(e,t){e.top=Math.max(e.top,t.top),e.left=Math.max(e.left,t.left),e.bottom=Math.max(e.bottom,t.bottom),e.right=Math.max(e.right,t.right)}function wV(e,t,n,s){const{pos:i,box:o}=n,r=e.maxPadding;if(!st(i)){n.size&&(e[i]-=n.size);const d=s[n.stack]||{size:0,count:1};d.size=Math.max(d.size,n.horizontal?o.height:o.width),n.size=d.size/d.count,e[i]+=n.size}o.getPadding&&e1(r,o.getPadding());const a=Math.max(0,t.outerWidth-x_(r,e,"left","right")),l=Math.max(0,t.outerHeight-x_(r,e,"top","bottom")),c=a!==e.w,u=l!==e.h;return e.w=a,e.h=l,n.horizontal?{same:c,other:u}:{same:u,other:c}}function xV(e){const t=e.maxPadding;function n(s){const i=Math.max(t[s]-e[s],0);return e[s]+=i,i}e.y+=n("top"),e.x+=n("left"),n("right"),n("bottom")}function kV(e,t){const n=t.maxPadding;function s(i){const o={left:0,top:0,right:0,bottom:0};return i.forEach(r=>{o[r]=Math.max(t[r],n[r])}),o}return s(e?["left","right"]:["top","bottom"])}function ua(e,t,n,s){const i=[];let o,r,a,l,c,u;for(o=0,r=e.length,c=0;oe==="left"?"right":e==="right"?"left":e,A_=(e,t,n)=>t==="top"||t==="left"?e[t]+n:e[t]-n,C_=(e,t)=>Math.min(t||e,e);function E_(e,t){const n=[],s=e.length/t,i=e.length;let o=0;for(;or+a)))return l}function UV(e,t){ut(e,n=>{const s=n.gc,i=s.length/2;let o;if(i>t){for(o=0;os?s:n,s=i&&n>s?n:s,{min:Mn(n,Mn(s,n)),max:Mn(s,Mn(n,s))}}getPadding(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}}getTicks(){return this.ticks}getLabels(){const t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]}getLabelItems(t=this.chart.chartArea){return this._labelItems||(this._labelItems=this._computeLabelItems(t))}beforeLayout(){this._cache={},this._dataLimitsCached=!1}beforeUpdate(){pt(this.options.beforeUpdate,[this])}update(t,n,s){const{beginAtZero:i,grace:o,ticks:r}=this.options,a=r.sampleSize;this.beforeUpdate(),this.maxWidth=t,this.maxHeight=n,this._margins=s=Object.assign({left:0,right:0,top:0,bottom:0},s),this.ticks=null,this._labelSizes=null,this._gridLineItems=null,this._labelItems=null,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this._maxLength=this.isHorizontal()?this.width+s.left+s.right:this.height+s.top+s.bottom,this._dataLimitsCached||(this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this._range=r4(this,o,i),this._dataLimitsCached=!0),this.beforeBuildTicks(),this.ticks=this.buildTicks()||[],this.afterBuildTicks();const l=a({width:r[P]||0,height:a[P]||0});return{first:C(0),last:C(n-1),widest:C(y),highest:C(x),widths:r,heights:a}}getLabelForValue(t){return t}getPixelForValue(t,n){return NaN}getValueForPixel(t){}getPixelForTick(t){const n=this.ticks;return t<0||t>n.length-1?null:this.getPixelForValue(n[t].value)}getPixelForDecimal(t){this._reversePixels&&(t=1-t);const n=this._startPixel+t*this._length;return RB(this._alignToPixels?lo(this.chart,n,0):n)}getDecimalForPixel(t){const n=(t-this._startPixel)/this._length;return this._reversePixels?1-n:n}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:n}=this;return t<0&&n<0?n:t>0&&n>0?t:0}getContext(t){const n=this.ticks||[];if(t>=0&&tn.length&&delete this._stacks,t.forEach((s,i)=>{n.filter(o=>o===s._dataset).length===0&&this._destroyDatasetMeta(i)})}buildOrUpdateControllers(){const t=[],n=this.data.datasets;let s,i;for(this._removeUnreferencedMetasets(),s=0,i=n.length;s{this.getDatasetMeta(n).controller.reset()},this)}reset(){this._resetElements(),this.notifyPlugins("reset")}update(t){const n=this.config;n.update();const s=this._options=n.createResolver(n.chartOptionScopes(),this.getContext()),i=this._animationsDisabled=!s.animation;if(this._updateScales(),this._checkEventBindings(),this._updateHiddenIndices(),this._plugins.invalidate(),this.notifyPlugins("beforeUpdate",{mode:t,cancelable:!0})===!1)return;const o=this.buildOrUpdateControllers();this.notifyPlugins("beforeElementsUpdate");let r=0;for(let c=0,u=this.data.datasets.length;c{c.reset()}),this._updateDatasets(t),this.notifyPlugins("afterUpdate",{mode:t}),this._layers.sort(R_("z","_idx"));const{_active:a,_lastEvent:l}=this;l?this._eventHandler(l,!0):a.length&&this._updateHoverStyles(a,a,!0),this.render()}_updateScales(){ut(this.scales,t=>{Gn.removeBox(this,t)}),this.ensureScalesHaveIDs(),this.buildOrUpdateScales()}_checkEventBindings(){const t=this.options,n=new Set(Object.keys(this._listeners)),s=new Set(t.events);(!Kg(n,s)||!!this._responsiveListeners!==t.responsive)&&(this.unbindEvents(),this.bindEvents())}_updateHiddenIndices(){const{_hiddenIndices:t}=this,n=this._getUniformDataChanges()||[];for(const{method:s,start:i,count:o}of n){const r=s==="_removeElements"?-o:o;v6(t,i,r)}}_getUniformDataChanges(){const t=this._dataChanges;if(!t||!t.length)return;this._dataChanges=[];const n=this.data.datasets.length,s=o=>new Set(t.filter(r=>r[0]===o).map((r,a)=>a+","+r.splice(1).join(","))),i=s(0);for(let o=1;o=0;--n)this._drawDataset(t[n]);this.notifyPlugins("afterDatasetsDraw")}_drawDataset(t){const n=this.ctx,s=t._clip,i=!s.disabled,o=y6(t,this.chartArea),r={meta:t,index:t.index,cancelable:!0};this.notifyPlugins("beforeDatasetDraw",r)!==!1&&(i&&bu(n,{left:s.left===!1?0:o.left-s.left,right:s.right===!1?this.width:o.right+s.right,top:s.top===!1?0:o.top-s.top,bottom:s.bottom===!1?this.height:o.bottom+s.bottom}),t.controller.draw(),i&&yu(n),r.cancelable=!1,this.notifyPlugins("afterDatasetDraw",r))}isPointInArea(t){return Js(t,this.chartArea,this._minPadding)}getElementsAtEventForMode(t,n,s,i){const o=gV.modes[n];return typeof o=="function"?o(this,t,s,i):[]}getDatasetMeta(t){const n=this.data.datasets[t],s=this._metasets;let i=s.filter(o=>o&&o._dataset===n).pop();return i||(i={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:n&&n.order||0,index:t,_dataset:n,_parsed:[],_sorted:!1},s.push(i)),i}getContext(){return this.$context||(this.$context=Ki(null,{chart:this,type:"chart"}))}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const n=this.data.datasets[t];if(!n)return!1;const s=this.getDatasetMeta(t);return typeof s.hidden=="boolean"?!s.hidden:!n.hidden}setDatasetVisibility(t,n){const s=this.getDatasetMeta(t);s.hidden=!n}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateVisibility(t,n,s){const i=s?"show":"hide",o=this.getDatasetMeta(t),r=o.controller._resolveAnimations(void 0,i);qa(n)?(o.data[n].hidden=!s,this.update()):(this.setDatasetVisibility(t,s),r.update(o,{visible:s}),this.update(a=>a.datasetIndex===t?i:void 0))}hide(t,n){this._updateVisibility(t,n,!1)}show(t,n){this._updateVisibility(t,n,!0)}_destroyDatasetMeta(t){const n=this._metasets[t];n&&n.controller&&n.controller._destroy(),delete this._metasets[t]}_stop(){let t,n;for(this.stop(),Hs.remove(this),t=0,n=this.data.datasets.length;te.height-s/2?"bottom":"center"}function yH(e,t,n,s){const{x:i,width:o}=s,r=n.caretSize+n.caretPadding;if(e==="left"&&i+o+r>t.width||e==="right"&&i-o-r<0)return!0}function wH(e,t,n,s){const{x:i,width:o}=n,{width:r,chartArea:{left:a,right:l}}=e;let c="center";return s==="center"?c=i<=(a+l)/2?"left":"right":i<=o/2?c="left":i>=r-o/2&&(c="right"),yH(c,e,t,n)&&(c="center"),c}function G_(e,t,n){const s=n.yAlign||t.yAlign||bH(e,n);return{xAlign:n.xAlign||t.xAlign||wH(e,t,n,s),yAlign:s}}function xH(e,t){let{x:n,width:s}=e;return t==="right"?n-=s:t==="center"&&(n-=s/2),n}function kH(e,t,n){let{y:s,height:i}=e;return t==="top"?s+=n:t==="bottom"?s-=i+n:s-=i/2,s}function J_(e,t,n,s){const{caretSize:i,caretPadding:o,cornerRadius:r}=e,{xAlign:a,yAlign:l}=n,c=i+o,{topLeft:u,topRight:d,bottomLeft:f,bottomRight:p}=$o(r);let g=xH(t,a);const _=kH(t,l,c);return l==="center"?a==="left"?g+=c:a==="right"&&(g-=c):a==="left"?g-=Math.max(u,f)+i:a==="right"&&(g+=Math.max(d,p)+i),{x:en(g,0,s.width-t.width),y:en(_,0,s.height-t.height)}}function Ql(e,t,n){const s=fn(n.padding);return t==="center"?e.x+e.width/2:t==="right"?e.x+e.width-s.right:e.x+s.left}function X_(e){return vs([],js(e))}function SH(e,t,n){return Ki(e,{tooltip:t,tooltipItems:n,type:"tooltip"})}function Q_(e,t){const n=t&&t.dataset&&t.dataset.tooltip&&t.dataset.tooltip.callbacks;return n?e.override(n):e}const g1={beforeTitle:Bs,title(e){if(e.length>0){const t=e[0],n=t.chart.data.labels,s=n?n.length:0;if(this&&this.options&&this.options.mode==="dataset")return t.dataset.label||"";if(t.label)return t.label;if(s>0&&t.dataIndex"u"?g1[t].call(n,s):i}class _h extends oi{constructor(t){super(),this.opacity=0,this._active=[],this._eventPosition=void 0,this._size=void 0,this._cachedAnimations=void 0,this._tooltipItems=[],this.$animations=void 0,this.$context=void 0,this.chart=t.chart,this.options=t.options,this.dataPoints=void 0,this.title=void 0,this.beforeBody=void 0,this.body=void 0,this.afterBody=void 0,this.footer=void 0,this.xAlign=void 0,this.yAlign=void 0,this.x=void 0,this.y=void 0,this.height=void 0,this.width=void 0,this.caretX=void 0,this.caretY=void 0,this.labelColors=void 0,this.labelPointStyles=void 0,this.labelTextColors=void 0}initialize(t){this.options=t,this._cachedAnimations=void 0,this.$context=void 0}_resolveAnimations(){const t=this._cachedAnimations;if(t)return t;const n=this.chart,s=this.options.setContext(this.getContext()),i=s.enabled&&n.options.animation&&s.animations,o=new J0(this.chart,i);return i._cacheable&&(this._cachedAnimations=Object.freeze(o)),o}getContext(){return this.$context||(this.$context=SH(this.chart.getContext(),this,this._tooltipItems))}getTitle(t,n){const{callbacks:s}=n,i=Sn(s,"beforeTitle",this,t),o=Sn(s,"title",this,t),r=Sn(s,"afterTitle",this,t);let a=[];return a=vs(a,js(i)),a=vs(a,js(o)),a=vs(a,js(r)),a}getBeforeBody(t,n){return X_(Sn(n.callbacks,"beforeBody",this,t))}getBody(t,n){const{callbacks:s}=n,i=[];return ut(t,o=>{const r={before:[],lines:[],after:[]},a=Q_(s,o);vs(r.before,js(Sn(a,"beforeLabel",this,o))),vs(r.lines,Sn(a,"label",this,o)),vs(r.after,js(Sn(a,"afterLabel",this,o))),i.push(r)}),i}getAfterBody(t,n){return X_(Sn(n.callbacks,"afterBody",this,t))}getFooter(t,n){const{callbacks:s}=n,i=Sn(s,"beforeFooter",this,t),o=Sn(s,"footer",this,t),r=Sn(s,"afterFooter",this,t);let a=[];return a=vs(a,js(i)),a=vs(a,js(o)),a=vs(a,js(r)),a}_createItems(t){const n=this._active,s=this.chart.data,i=[],o=[],r=[];let a=[],l,c;for(l=0,c=n.length;li?{start:t-n,end:t}:{start:t,end:t+n}}function OH(e){const t={l:e.left+e._padding.left,r:e.right-e._padding.right,t:e.top+e._padding.top,b:e.bottom-e._padding.bottom},n=Object.assign({},t),s=[],i=[],o=e._pointLabels.length,r=e.options.pointLabels,a=r.centerPointLabels?wt/o:0;for(let l=0;l{const i=pt(this.options.pointLabels.callback,[n,s],this);return i||i===0?i:""}).filter((n,s)=>this.chart.getDataVisibility(s))}fit(){const t=this.options;t.display&&t.pointLabels.display?OH(this):this.setCenterPoint(0,0,0,0)}setCenterPoint(t,n,s,i){this.xCenter+=Math.floor((t-n)/2),this.yCenter+=Math.floor((s-i)/2),this.drawingArea-=Math.min(this.drawingArea/2,Math.max(t,n,s,i))}getIndexAngle(t){const n=yt/(this._pointLabels.length||1),s=this.options.startAngle||0;return Dn(t*n+as(s))}getDistanceFromCenterForValue(t){if(ot(t))return NaN;const n=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*n:(t-this.min)*n}getValueForDistanceFromCenter(t){if(ot(t))return NaN;const n=t/(this.drawingArea/(this.max-this.min));return this.options.reverse?this.max-n:this.min+n}getPointLabelContext(t){const n=this._pointLabels||[];if(t>=0&&t+_)}getLabelForValue(t){const n=this._adapter,s=this.options.time;return s.tooltipFormat?n.format(t,s.tooltipFormat):n.format(t,s.displayFormats.datetime)}format(t,n){const i=this.options.time.displayFormats,o=this._unit,r=n||i[o];return this._adapter.format(t,r)}_tickFormatFunction(t,n,s,i){const o=this.options,r=o.ticks.callback;if(r)return pt(r,[t,n,s],this);const a=o.time.displayFormats,l=this._unit,c=this._majorUnit,u=l&&a[l],d=c&&a[c],f=s[n],p=c&&d&&f&&f.major;return this._adapter.format(t,i||(p?d:u))}generateTickLabels(t){let n,s,i;for(n=0,s=t.length;n0?a:1}getDataTimestamps(){let t=this._cache.data||[],n,s;if(t.length)return t;const i=this.getMatchingVisibleMetas();if(this._normalized&&i.length)return this._cache.data=i[0].controller.getAllParsedValues(this);for(n=0,s=i.length;n=e[s].pos&&t<=e[i].pos&&({lo:s,hi:i}=Gs(e,"pos",t)),{pos:o,time:a}=e[s],{pos:r,time:l}=e[i]):(t>=e[s].time&&t<=e[i].time&&({lo:s,hi:i}=Gs(e,"time",t)),{time:o,pos:a}=e[s],{time:r,pos:l}=e[i]);const c=r-o;return c?a+(l-a)*(t-o)/c:a}class xh extends Za{constructor(t){super(t),this._table=[],this._minPos=void 0,this._tableRange=void 0}initOffsets(){const t=this._getTimestampsForTable(),n=this._table=this.buildLookupTable(t);this._minPos=Zl(n,this.min),this._tableRange=Zl(n,this.max)-this._minPos,super.initOffsets(t)}buildLookupTable(t){const{min:n,max:s}=this,i=[],o=[];let r,a,l,c,u;for(r=0,a=t.length;r=n&&c<=s&&i.push(c);if(i.length<2)return[{time:n,pos:0},{time:s,pos:1}];for(r=0,a=i.length;ri-o)}_getTimestampsForTable(){let t=this._cache.all||[];if(t.length)return t;const n=this.getDataTimestamps(),s=this.getLabelTimestamps();return n.length&&s.length?t=this.normalize(n.concat(s)):t=n.length?n:s,t=this._cache.all=t,t}getDecimalForValue(t){return(Zl(this._table,t)-this._minPos)/this._tableRange}getValueForPixel(t){const n=this._offsets,s=this.getDecimalForPixel(t)/n.factor-n.end;return Zl(this._table,s*this._tableRange+this._minPos,!0)}}le(xh,"id","timeseries"),le(xh,"defaults",Za.defaults);const v1={data:{type:Object,required:!0},options:{type:Object,default:()=>({})},plugins:{type:Array,default:()=>[]},datasetIdKey:{type:String,default:"label"},updateMode:{type:String,default:void 0}},qH={ariaLabel:{type:String},ariaDescribedby:{type:String}},GH={type:{type:String,required:!0},...v1,...qH},JH=Qb[0]==="2"?(e,t)=>Object.assign(e,{attrs:t}):(e,t)=>Object.assign(e,t);function er(e){return eu(e)?Ze(e):e}function XH(e){let t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:e;return eu(t)?new Proxy(e,{}):e}function QH(e,t){const n=e.options;n&&t&&Object.assign(n,t)}function b1(e,t){e.labels=t}function y1(e,t,n){const s=[];e.datasets=t.map(i=>{const o=e.datasets.find(r=>r[n]===i[n]);return!o||!i.data||s.includes(o)?{...i}:(s.push(o),Object.assign(o,i),o)})}function ZH(e,t){const n={labels:[],datasets:[]};return b1(n,e.labels),y1(n,e.datasets,t),n}const e8=Ft({props:GH,setup(e,t){let{expose:n,slots:s}=t;const i=be(null),o=of(null);n({chart:o});const r=()=>{if(!i.value)return;const{type:c,data:u,options:d,plugins:f,datasetIdKey:p}=e,g=ZH(u,p),_=XH(g,u);o.value=new xu(i.value,{type:c,data:_,options:{...d},plugins:f})},a=()=>{const c=Ze(o.value);c&&(c.destroy(),o.value=null)},l=c=>{c.update(e.updateMode)};return Gt(r),hf(a),Vt([()=>e.options,()=>e.data],(c,u)=>{let[d,f]=c,[p,g]=u;const _=Ze(o.value);if(!_)return;let b=!1;if(d){const w=er(d),$=er(p);w&&w!==$&&(QH(_,w),b=!0)}if(f){const w=er(f.labels),$=er(g.labels),A=er(f.datasets),T=er(g.datasets);w!==$&&(b1(_.config.data,w),b=!0),A&&A!==T&&(y1(_.config.data,A,e.datasetIdKey),b=!0)}b&&tn(()=>{l(_)})},{deep:!0}),()=>Mo("canvas",{role:"img",ariaLabel:e.ariaLabel,ariaDescribedby:e.ariaDescribedby,ref:i},[Mo("p",{},[s.default?s.default():""])])}});function w1(e,t){return xu.register(t),Ft({props:v1,setup(n,s){let{expose:i}=s;const o=of(null),r=a=>{o.value=a==null?void 0:a.chart};return i({chart:o}),()=>Mo(e8,JH({ref:r},{type:e,...n}))}})}const t8=w1("bar",Ma),n8=w1("line",Ta);function ti(e){return Array.isArray?Array.isArray(e):S1(e)==="[object Array]"}const s8=1/0;function i8(e){if(typeof e=="string")return e;let t=e+"";return t=="0"&&1/e==-s8?"-0":t}function o8(e){return e==null?"":i8(e)}function $s(e){return typeof e=="string"}function x1(e){return typeof e=="number"}function r8(e){return e===!0||e===!1||a8(e)&&S1(e)=="[object Boolean]"}function k1(e){return typeof e=="object"}function a8(e){return k1(e)&&e!==null}function On(e){return e!=null}function Ed(e){return!e.trim().length}function S1(e){return e==null?e===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(e)}const l8="Incorrect 'index' type",c8=e=>`Invalid value for key ${e}`,u8=e=>`Pattern length exceeds max of ${e}.`,d8=e=>`Missing ${e} property in key`,h8=e=>`Property 'weight' in key '${e}' must be a positive integer`,cv=Object.prototype.hasOwnProperty;class f8{constructor(t){this._keys=[],this._keyMap={};let n=0;t.forEach(s=>{let i=$1(s);this._keys.push(i),this._keyMap[i.id]=i,n+=i.weight}),this._keys.forEach(s=>{s.weight/=n})}get(t){return this._keyMap[t]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function $1(e){let t=null,n=null,s=null,i=1,o=null;if($s(e)||ti(e))s=e,t=uv(e),n=kh(e);else{if(!cv.call(e,"name"))throw new Error(d8("name"));const r=e.name;if(s=r,cv.call(e,"weight")&&(i=e.weight,i<=0))throw new Error(h8(r));t=uv(r),n=kh(r),o=e.getFn}return{path:t,id:n,weight:i,src:s,getFn:o}}function uv(e){return ti(e)?e:e.split(".")}function kh(e){return ti(e)?e.join("."):e}function p8(e,t){let n=[],s=!1;const i=(o,r,a)=>{if(On(o))if(!r[a])n.push(o);else{let l=r[a];const c=o[l];if(!On(c))return;if(a===r.length-1&&($s(c)||x1(c)||r8(c)))n.push(o8(c));else if(ti(c)){s=!0;for(let u=0,d=c.length;u{let r=i.getFn?i.getFn(t):this.getFn(t,i.path);if(On(r)){if(ti(r)){let a=[];const l=[{nestedArrIndex:-1,value:r}];for(;l.length;){const{nestedArrIndex:c,value:u}=l.pop();if(On(u))if($s(u)&&!Ed(u)){let d={v:u,i:c,n:this.norm.get(u)};a.push(d)}else ti(u)&&u.forEach((d,f)=>{l.push({nestedArrIndex:f,value:d})})}s.$[o]=a}else if($s(r)&&!Ed(r)){let a={v:r,n:this.norm.get(r)};s.$[o]=a}}}),this.records.push(s)}toJSON(){return{keys:this.keys,records:this.records}}}function A1(e,t,{getFn:n=qe.getFn,fieldNormWeight:s=qe.fieldNormWeight}={}){const i=new op({getFn:n,fieldNormWeight:s});return i.setKeys(e.map($1)),i.setSources(t),i.create(),i}function w8(e,{getFn:t=qe.getFn,fieldNormWeight:n=qe.fieldNormWeight}={}){const{keys:s,records:i}=e,o=new op({getFn:t,fieldNormWeight:n});return o.setKeys(s),o.setIndexRecords(i),o}function ec(e,{errors:t=0,currentLocation:n=0,expectedLocation:s=0,distance:i=qe.distance,ignoreLocation:o=qe.ignoreLocation}={}){const r=t/e.length;if(o)return r;const a=Math.abs(s-n);return i?r+a/i:a?1:r}function x8(e=[],t=qe.minMatchCharLength){let n=[],s=-1,i=-1,o=0;for(let r=e.length;o{this.chunks.push({pattern:f,alphabet:S8(f),startIndex:p})},d=this.pattern.length;if(d>_o){let f=0;const p=d%_o,g=d-p;for(;f=55296&&o<=56319&&s>i+1){var r=t.charCodeAt(i+1);r>=56320&&r<=57343&&(o=(o-55296)*1024+r-56320+65536,i+=1)}if(o<128){n.push(o);continue}if(o<2048){n.push(o>>6|192),n.push(o&63|128);continue}if(o<55296||o>=57344&&o<65536){n.push(o>>12|224),n.push(o>>6&63|128),n.push(o&63|128);continue}if(o>=65536&&o<=1114111){n.push(o>>18|240),n.push(o>>12&63|128),n.push(o>>6&63|128),n.push(o&63|128);continue}n.push(239,191,189)}return new Uint8Array(n).buffer};const eW=Zj,tW=Gi;function Ir(e){this.mode=tW.BYTE,typeof e=="string"&&(e=eW(e)),this.data=new Uint8Array(e)}Ir.getBitsLength=function(t){return t*8};Ir.prototype.getLength=function(){return this.data.length};Ir.prototype.getBitsLength=function(){return Ir.getBitsLength(this.data.length)};Ir.prototype.write=function(e){for(let t=0,n=this.data.length;ts[this.dashboardConfigurationStore.Configuration.Server.dashboard_sort]?-1:0):t.slice().sort((n,s)=>n[this.dashboardConfigurationStore.Configuration.Server.dashboard_sort]s[this.dashboardConfigurationStore.Configuration.Server.dashboard_sort]?1:0)}}},pn=e=>(Kt("data-v-25208f9e"),e=e(),qt(),e),zK={key:0,class:"container-md"},YK={class:"d-flex align-items-center"},UK=pn(()=>h("small",{CLASS:"text-muted"},"CONFIGURATION",-1)),KK={class:"d-flex align-items-center gap-3"},qK={class:"mb-0"},GK={class:"card rounded-3 bg-transparent shadow-sm ms-auto"},JK={class:"card-body py-2 d-flex align-items-center"},XK=pn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Status")],-1)),QK={class:"form-check form-switch ms-auto"},ZK=["for"],e7={key:0,class:"spinner-border spinner-border-sm","aria-hidden":"true"},t7=["disabled","id"],n7={class:"row mt-3 gy-2 gx-2 mb-2"},s7={class:"col-6 col-lg-3"},i7={class:"card rounded-3 bg-transparent shadow-sm"},o7={class:"card-body py-2"},r7=pn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Address")],-1)),a7={class:"col-6 col-lg-3"},l7={class:"card rounded-3 bg-transparent shadow-sm"},c7={class:"card-body py-2"},u7=pn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Listen Port")],-1)),d7={style:{"word-break":"break-all"},class:"col-12 col-lg-6"},h7={class:"card rounded-3 bg-transparent shadow-sm"},f7={class:"card-body py-2"},p7=pn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Public Key")],-1)),m7={class:"row gx-2 gy-2 mb-2"},g7={class:"col-6 col-lg-3"},_7={class:"card rounded-3 bg-transparent shadow-sm"},v7={class:"card-body d-flex"},b7=pn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Connected Peers")],-1)),y7={class:"h4"},w7=pn(()=>h("i",{class:"bi bi-ethernet ms-auto h2 text-muted"},null,-1)),x7={class:"col-6 col-lg-3"},k7={class:"card rounded-3 bg-transparent shadow-sm"},S7={class:"card-body d-flex"},$7=pn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Total Usage")],-1)),A7={class:"h4"},C7=pn(()=>h("i",{class:"bi bi-arrow-down-up ms-auto h2 text-muted"},null,-1)),E7={class:"col-6 col-lg-3"},P7={class:"card rounded-3 bg-transparent shadow-sm"},M7={class:"card-body d-flex"},T7=pn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Total Received")],-1)),D7={class:"h4 text-primary"},O7=pn(()=>h("i",{class:"bi bi-arrow-down ms-auto h2 text-muted"},null,-1)),I7={class:"col-6 col-lg-3"},R7={class:"card rounded-3 bg-transparent shadow-sm"},L7={class:"card-body d-flex"},N7=pn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Total Sent")],-1)),F7={class:"h4 text-success"},B7=pn(()=>h("i",{class:"bi bi-arrow-up ms-auto h2 text-muted"},null,-1)),V7={class:"row gx-2 gy-2 mb-3"},H7={class:"col-12 col-lg-6"},j7={class:"card rounded-3 bg-transparent shadow-sm",style:{height:"270px"}},W7=pn(()=>h("div",{class:"card-header bg-transparent border-0"},[h("small",{class:"text-muted"},"Peers Total Data Usage")],-1)),z7={class:"card-body pt-1"},Y7={class:"col-sm col-lg-3"},U7={class:"card rounded-3 bg-transparent shadow-sm",style:{height:"270px"}},K7=pn(()=>h("div",{class:"card-header bg-transparent border-0"},[h("small",{class:"text-muted"},"Real Time Received Data Usage")],-1)),q7={class:"card-body pt-1"},G7={class:"col-sm col-lg-3"},J7={class:"card rounded-3 bg-transparent shadow-sm",style:{height:"270px"}},X7=pn(()=>h("div",{class:"card-header bg-transparent border-0"},[h("small",{class:"text-muted"},"Real Time Sent Data Usage")],-1)),Q7={class:"card-body pt-1"},Z7={class:"mb-3"};function e9(e,t,n,s,i,o){const r=je("Bar"),a=je("Line"),l=je("PeerSearch"),c=je("Peer"),u=je("PeerSettings"),d=je("PeerQRCode"),f=je("PeerJobs"),p=je("PeerJobsAllModal"),g=je("PeerJobsLogsModal"),_=je("PeerShareLinkModal");return this.loading?re("",!0):(D(),F("div",zK,[h("div",YK,[h("div",null,[UK,h("div",KK,[h("h1",qK,[h("samp",null,_e(this.configurationInfo.Name),1)])])]),h("div",GK,[h("div",JK,[h("div",null,[XK,h("div",QK,[h("label",{class:"form-check-label",style:{cursor:"pointer"},for:"switch"+this.configurationInfo.id},[ye(_e(this.configurationToggling?"Turning ":"")+" "+_e(this.configurationInfo.Status?"On":"Off")+" ",1),this.configurationToggling?(D(),F("span",e7)):re("",!0)],8,ZK),Re(h("input",{class:"form-check-input",style:{cursor:"pointer"},disabled:this.configurationToggling,type:"checkbox",role:"switch",id:"switch"+this.configurationInfo.id,onChange:t[0]||(t[0]=b=>this.toggle()),"onUpdate:modelValue":t[1]||(t[1]=b=>this.configurationInfo.Status=b)},null,40,t7),[[In,this.configurationInfo.Status]])])]),h("div",{class:Ee(["dot ms-5",{active:this.configurationInfo.Status}])},null,2)])])]),h("div",n7,[h("div",s7,[h("div",i7,[h("div",o7,[r7,ye(" "+_e(this.configurationInfo.Address),1)])])]),h("div",a7,[h("div",l7,[h("div",c7,[u7,ye(" "+_e(this.configurationInfo.ListenPort),1)])])]),h("div",d7,[h("div",h7,[h("div",f7,[p7,h("samp",null,_e(this.configurationInfo.PublicKey),1)])])])]),h("div",m7,[h("div",g7,[h("div",_7,[h("div",v7,[h("div",null,[b7,h("strong",y7,_e(o.configurationSummary.connectedPeers),1)]),w7])])]),h("div",x7,[h("div",k7,[h("div",S7,[h("div",null,[$7,h("strong",A7,_e(o.configurationSummary.totalUsage)+" GB",1)]),C7])])]),h("div",E7,[h("div",P7,[h("div",M7,[h("div",null,[T7,h("strong",D7,_e(o.configurationSummary.totalReceive)+" GB",1)]),O7])])]),h("div",I7,[h("div",R7,[h("div",L7,[h("div",null,[N7,h("strong",F7,_e(o.configurationSummary.totalSent)+" GB",1)]),B7])])])]),h("div",V7,[h("div",H7,[h("div",j7,[W7,h("div",z7,[$e(r,{data:o.individualDataUsage,options:o.individualDataUsageChartOption,style:{width:"100%",height:"200px","max-height":"200px"}},null,8,["data","options"])])])]),h("div",Y7,[h("div",U7,[K7,h("div",q7,[$e(a,{options:o.chartOptions,data:o.receiveData,style:{width:"100%",height:"200px","max-height":"200px"}},null,8,["options","data"])])])]),h("div",G7,[h("div",J7,[X7,h("div",Q7,[$e(a,{options:o.chartOptions,data:o.sentData,style:{width:"100%",height:"200px","max-height":"200px"}},null,8,["options","data"])])])])]),h("div",Z7,[$e(l,{onJobsAll:t[2]||(t[2]=b=>this.peerScheduleJobsAll.modalOpen=!0),onJobLogs:t[3]||(t[3]=b=>this.peerScheduleJobsLogs.modalOpen=!0),configuration:this.configurationInfo},null,8,["configuration"]),$e(Wi,{name:"list",tag:"div",class:"row gx-2 gy-2 z-0"},{default:Me(()=>[(D(!0),F(Te,null,Ke(this.searchPeers,b=>(D(),F("div",{class:"col-12 col-lg-6 col-xl-4",key:b.id},[$e(c,{Peer:b,onShare:w=>{this.peerShare.selectedPeer=b.id,this.peerShare.modalOpen=!0},onRefresh:t[4]||(t[4]=w=>this.getPeers()),onJobs:w=>{i.peerScheduleJobs.modalOpen=!0,i.peerScheduleJobs.selectedPeer=this.configurationPeers.find($=>$.id===b.id)},onSetting:w=>{i.peerSetting.modalOpen=!0,i.peerSetting.selectedPeer=this.configurationPeers.find($=>$.id===b.id)},onQrcode:t[5]||(t[5]=w=>{this.peerQRCode.peerConfigData=w,this.peerQRCode.modalOpen=!0})},null,8,["Peer","onShare","onJobs","onSetting"])]))),128))]),_:1})]),$e(Ct,{name:"zoom"},{default:Me(()=>[this.peerSetting.modalOpen?(D(),Ne(u,{key:"settings",selectedPeer:this.peerSetting.selectedPeer,onRefresh:t[6]||(t[6]=b=>this.getPeers()),onClose:t[7]||(t[7]=b=>this.peerSetting.modalOpen=!1)},null,8,["selectedPeer"])):re("",!0)]),_:1}),$e(Ct,{name:"zoom"},{default:Me(()=>[i.peerQRCode.modalOpen?(D(),Ne(d,{peerConfigData:this.peerQRCode.peerConfigData,key:"qrcode",onClose:t[8]||(t[8]=b=>this.peerQRCode.modalOpen=!1)},null,8,["peerConfigData"])):re("",!0)]),_:1}),$e(Ct,{name:"zoom"},{default:Me(()=>[this.peerScheduleJobs.modalOpen?(D(),Ne(f,{key:0,onRefresh:t[9]||(t[9]=b=>this.getPeers()),selectedPeer:this.peerScheduleJobs.selectedPeer,onClose:t[10]||(t[10]=b=>this.peerScheduleJobs.modalOpen=!1)},null,8,["selectedPeer"])):re("",!0)]),_:1}),$e(Ct,{name:"zoom"},{default:Me(()=>[this.peerScheduleJobsAll.modalOpen?(D(),Ne(p,{key:0,onRefresh:t[11]||(t[11]=b=>this.getPeers()),onClose:t[12]||(t[12]=b=>this.peerScheduleJobsAll.modalOpen=!1),configurationPeers:this.configurationPeers},null,8,["configurationPeers"])):re("",!0)]),_:1}),$e(Ct,{name:"zoom"},{default:Me(()=>[this.peerScheduleJobsLogs.modalOpen?(D(),Ne(g,{key:0,onClose:t[13]||(t[13]=b=>this.peerScheduleJobsLogs.modalOpen=!1),configurationInfo:this.configurationInfo},null,8,["configurationInfo"])):re("",!0)]),_:1}),$e(Ct,{name:"zoom"},{default:Me(()=>[this.peerShare.modalOpen?(D(),Ne(_,{key:0,onClose:t[14]||(t[14]=b=>{this.peerShare.modalOpen=!1,this.peerShare.selectedPeer=void 0}),peer:this.configurationPeers.find(b=>b.id===this.peerShare.selectedPeer)},null,8,["peer"])):re("",!0)]),_:1})]))}const t9=ze(WK,[["render",e9],["__scopeId","data-v-25208f9e"]]),n9={name:"ping",data(){return{loading:!1,cips:{},selectedConfiguration:void 0,selectedPeer:void 0,selectedIp:void 0,count:4,pingResult:void 0,pinging:!1}},setup(){return{store:et()}},mounted(){$t("/api/ping/getAllPeersIpAddress",{},e=>{e.status&&(this.loading=!0,this.cips=e.data,console.log(this.cips))})},methods:{execute(){this.selectedIp&&(this.pinging=!0,this.pingResult=void 0,$t("/api/ping/execute",{ipAddress:this.selectedIp,count:this.count},e=>{e.status?this.pingResult=e.data:this.store.newMessage("Server",e.message,"danger")}))}},watch:{selectedConfiguration(){this.selectedPeer=void 0,this.selectedIp=void 0},selectedPeer(){this.selectedIp=void 0}}},Hn=e=>(Kt("data-v-7b32cdf7"),e=e(),qt(),e),s9={class:"mt-md-5 mt-3 text-body"},i9={class:"container"},o9=Hn(()=>h("h3",{class:"mb-3 text-body"},"Ping",-1)),r9={class:"row"},a9={class:"col-sm-4 d-flex gap-2 flex-column"},l9=Hn(()=>h("label",{class:"mb-1 text-muted",for:"configuration"},[h("small",null,"Configuration")],-1)),c9=Hn(()=>h("option",{disabled:"",selected:"",value:void 0},"Select a Configuration...",-1)),u9=["value"],d9=Hn(()=>h("label",{class:"mb-1 text-muted",for:"peer"},[h("small",null,"Peer")],-1)),h9=["disabled"],f9=Hn(()=>h("option",{disabled:"",selected:"",value:void 0},"Select a Peer...",-1)),p9=["value"],m9=Hn(()=>h("label",{class:"mb-1 text-muted",for:"ip"},[h("small",null,"IP Address")],-1)),g9=["disabled"],_9=Hn(()=>h("option",{disabled:"",selected:"",value:void 0},"Select a IP...",-1)),v9=Hn(()=>h("label",{class:"mb-1 text-muted",for:"count"},[h("small",null,"Ping Count")],-1)),b9=["disabled"],y9=Hn(()=>h("i",{class:"bi bi-person-walking me-2"},null,-1)),w9={class:"col-sm-8"},x9={key:"pingPlaceholder"},k9={key:"pingResult",class:"d-flex flex-column gap-2 w-100"},S9={class:"card rounded-3 bg-transparent shadow-sm animate__animated animate__fadeIn",style:{"animation-delay":"0.15s"}},$9={class:"card-body"},A9=Hn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Address")],-1)),C9={class:"card rounded-3 bg-transparent shadow-sm animate__animated animate__fadeIn",style:{"animation-delay":"0.3s"}},E9={class:"card-body"},P9=Hn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Is Alive")],-1)),M9={class:"card rounded-3 bg-transparent shadow-sm animate__animated animate__fadeIn",style:{"animation-delay":"0.45s"}},T9={class:"card-body"},D9=Hn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Average / Min / Max Round Trip Time")],-1)),O9={class:"card rounded-3 bg-transparent shadow-sm animate__animated animate__fadeIn",style:{"animation-delay":"0.6s"}},I9={class:"card-body"},R9=Hn(()=>h("p",{class:"mb-0 text-muted"},[h("small",null,"Sent / Received / Lost Package")],-1));function L9(e,t,n,s,i,o){return D(),F("div",s9,[h("div",i9,[o9,h("div",r9,[h("div",a9,[h("div",null,[l9,Re(h("select",{class:"form-select","onUpdate:modelValue":t[0]||(t[0]=r=>this.selectedConfiguration=r)},[c9,(D(!0),F(Te,null,Ke(this.cips,(r,a)=>(D(),F("option",{value:a},_e(a),9,u9))),256))],512),[[hc,this.selectedConfiguration]])]),h("div",null,[d9,Re(h("select",{id:"peer",class:"form-select","onUpdate:modelValue":t[1]||(t[1]=r=>this.selectedPeer=r),disabled:this.selectedConfiguration===void 0},[f9,this.selectedConfiguration!==void 0?(D(!0),F(Te,{key:0},Ke(this.cips[this.selectedConfiguration],(r,a)=>(D(),F("option",{value:a},_e(a),9,p9))),256)):re("",!0)],8,h9),[[hc,this.selectedPeer]])]),h("div",null,[m9,Re(h("select",{id:"ip",class:"form-select","onUpdate:modelValue":t[2]||(t[2]=r=>this.selectedIp=r),disabled:this.selectedPeer===void 0},[_9,this.selectedPeer!==void 0?(D(!0),F(Te,{key:0},Ke(this.cips[this.selectedConfiguration][this.selectedPeer].allowed_ips,r=>(D(),F("option",null,_e(r),1))),256)):re("",!0)],8,g9),[[hc,this.selectedIp]])]),h("div",null,[v9,Re(h("input",{class:"form-control",type:"number","onUpdate:modelValue":t[3]||(t[3]=r=>this.count=r),min:"1",id:"count",placeholder:"How many times you want to ping?"},null,512),[[We,this.count]])]),h("button",{class:"btn btn-primary rounded-3 mt-3",disabled:!this.selectedIp,onClick:t[4]||(t[4]=r=>this.execute())},[y9,ye("Go! ")],8,b9)]),h("div",w9,[$e(Wi,{name:"ping"},{default:Me(()=>[this.pingResult?(D(),F("div",k9,[h("div",S9,[h("div",$9,[A9,ye(" "+_e(this.pingResult.address),1)])]),h("div",C9,[h("div",E9,[P9,h("span",{class:Ee([this.pingResult.is_alive?"text-success":"text-danger"])},[h("i",{class:Ee(["bi me-1",[this.pingResult.is_alive?"bi-check-circle-fill":"bi-x-circle-fill"]])},null,2),ye(" "+_e(this.pingResult.is_alive?"Yes":"No"),1)],2)])]),h("div",M9,[h("div",T9,[D9,h("samp",null,_e(this.pingResult.avg_rtt)+"ms / "+_e(this.pingResult.min_rtt)+"ms / "+_e(this.pingResult.max_rtt)+"ms ",1)])]),h("div",O9,[h("div",I9,[R9,h("samp",null,_e(this.pingResult.package_sent)+" / "+_e(this.pingResult.package_received)+" / "+_e(this.pingResult.package_loss),1)])])])):(D(),F("div",x9,[(D(),F(Te,null,Ke(4,r=>h("div",{class:Ee(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.pinging}]),style:Wt({"animation-delay":`${r*.15}s`})},null,6)),64))]))]),_:1})])])])])}const N9=ze(n9,[["render",L9],["__scopeId","data-v-7b32cdf7"]]),F9={name:"traceroute",data(){return{tracing:!1,ipAddress:void 0,tracerouteResult:void 0}},setup(){return{store:Bn()}},methods:{execute(){this.ipAddress&&(this.tracing=!0,this.tracerouteResult=void 0,$t("/api/traceroute/execute",{ipAddress:this.ipAddress},e=>{e.status?this.tracerouteResult=e.data:this.store.newMessage("Server",e.message,"danger"),this.tracing=!1}))}}},Pu=e=>(Kt("data-v-606c2c93"),e=e(),qt(),e),B9={class:"mt-md-5 mt-3 text-body"},V9={class:"container-md"},H9=Pu(()=>h("h3",{class:"mb-3 text-body"},"Traceroute",-1)),j9={class:"row"},W9={class:"col-sm-4 d-flex gap-2 flex-column"},z9=Pu(()=>h("label",{class:"mb-1 text-muted",for:"ipAddress"},[h("small",null,"IP Address")],-1)),Y9=["disabled"],U9=Pu(()=>h("i",{class:"bi bi-bullseye me-2"},null,-1)),K9={class:"col-sm-8 position-relative"},q9={key:"pingPlaceholder"},G9={key:"table",class:"w-100"},J9={class:"table table-borderless rounded-3 w-100"},X9=Pu(()=>h("thead",null,[h("tr",null,[h("th",{scope:"col"},"Hop"),h("th",{scope:"col"},"IP Address"),h("th",{scope:"col"},"Average / Min / Max Round Trip Time")])],-1));function Q9(e,t,n,s,i,o){return D(),F("div",B9,[h("div",V9,[H9,h("div",j9,[h("div",W9,[h("div",null,[z9,Re(h("input",{id:"ipAddress",class:"form-control","onUpdate:modelValue":t[0]||(t[0]=r=>this.ipAddress=r),type:"text",placeholder:"Enter an IP Address you want to trace :)"},null,512),[[We,this.ipAddress]])]),h("button",{class:"btn btn-primary rounded-3 mt-3",disabled:!this.store.regexCheckIP(this.ipAddress)||this.tracing,onClick:t[1]||(t[1]=r=>this.execute())},[U9,ye(" "+_e(this.tracing?"Tracing...":"Trace It!"),1)],8,Y9)]),h("div",K9,[$e(Wi,{name:"ping"},{default:Me(()=>[this.tracerouteResult?(D(),F("div",G9,[h("table",J9,[X9,h("tbody",null,[(D(!0),F(Te,null,Ke(this.tracerouteResult,(r,a)=>(D(),F("tr",{class:"animate__fadeInUp animate__animated",style:Wt({"animation-delay":`${a*.05}s`})},[h("td",null,_e(r.hop),1),h("td",null,_e(r.ip),1),h("td",null,_e(r.avg_rtt)+" / "+_e(r.min_rtt)+" / "+_e(r.max_rtt),1)],4))),256))])])])):(D(),F("div",q9,[(D(),F(Te,null,Ke(10,r=>h("div",{class:Ee(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.tracing}]),style:Wt({"animation-delay":`${r*.05}s`})},null,6)),64))]))]),_:1})])])])])}const Z9=ze(F9,[["render",Q9],["__scopeId","data-v-606c2c93"]]),eq={name:"totp",async setup(){const e=et();let t="";return await $t("/api/Welcome_GetTotpLink",{},n=>{n.status&&(t=n.data)}),{l:t,store:e}},mounted(){this.l&&Bo.toCanvas(document.getElementById("qrcode"),this.l,function(e){})},data(){return{totp:"",totpInvalidMessage:"",verified:!1}},methods:{validateTotp(){}},watch:{totp(e){const t=document.querySelector("#totp");t.classList.remove("is-invalid","is-valid"),e.length===6&&(console.log(e),/[0-9]{6}/.test(e)?ft("/api/Welcome_VerifyTotpLink",{totp:e},n=>{n.status?(this.verified=!0,t.classList.add("is-valid"),this.$emit("verified")):(t.classList.add("is-invalid"),this.totpInvalidMessage="TOTP does not match.")}):(t.classList.add("is-invalid"),this.totpInvalidMessage="TOTP can only contain numbers"))}}},tq=["data-bs-theme"],nq={class:"m-auto text-body",style:{width:"500px"}},sq={class:"d-flex flex-column"},iq=h("h1",{class:"dashboardLogo display-4"},"Multi-Factor Authentication",-1),oq=h("p",{class:"mb-2"},[h("small",{class:"text-muted"},"1. Please scan the following QR Code to generate TOTP")],-1),rq=h("canvas",{id:"qrcode",class:"rounded-3 mb-2"},null,-1),aq={class:"p-3 bg-body-secondary rounded-3 border mb-3"},lq=h("p",{class:"text-muted mb-0"},[h("small",null,"Or you can click the link below:")],-1),cq=["href"],uq={style:{"line-break":"anywhere"}},dq=h("label",{for:"totp",class:"mb-2"},[h("small",{class:"text-muted"},"2. Enter the TOTP generated by your authenticator to verify")],-1),hq={class:"form-group mb-2"},fq=["disabled"],pq={class:"invalid-feedback"},mq=h("div",{class:"valid-feedback"}," TOTP verified! ",-1),gq=h("div",{class:"alert alert-warning rounded-3"},[h("i",{class:"bi bi-exclamation-triangle-fill me-2"}),ye(" If you ever lost your TOTP and can't login, please follow instruction on "),h("a",{href:"https://github.com/donaldzou/WGDashboard",target:"_blank"},"readme.md"),ye(" to reset. ")],-1),_q=h("hr",null,null,-1),vq={class:"d-flex gap-3 mt-5 flex-column"},bq=h("i",{class:"bi bi-chevron-right ms-auto"},null,-1),yq=h("i",{class:"bi bi-chevron-right ms-auto"},null,-1);function wq(e,t,n,s,i,o){const r=je("RouterLink");return D(),F("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[h("div",nq,[h("div",sq,[h("div",null,[iq,oq,rq,h("div",aq,[lq,h("a",{href:this.l},[h("code",uq,_e(this.l),1)],8,cq)]),dq,h("div",hq,[Re(h("input",{class:"form-control text-center totp",id:"totp",maxlength:"6",type:"text",inputmode:"numeric",autocomplete:"one-time-code","onUpdate:modelValue":t[0]||(t[0]=a=>this.totp=a),disabled:this.verified},null,8,fq),[[We,this.totp]]),h("div",pq,_e(this.totpInvalidMessage),1),mq]),gq]),_q,h("div",vq,[this.verified?(D(),Ne(r,{key:1,to:"/",class:"btn btn-dark btn-lg d-flex btn-brand shadow align-items-center flex-grow-1 rounded-3"},{default:Me(()=>[ye(" Complete "),yq]),_:1})):(D(),Ne(r,{key:0,to:"/",class:"btn bg-secondary-subtle text-secondary-emphasis rounded-3 flex-grow-1 btn-lg border-1 border-secondary-subtle shadow d-flex"},{default:Me(()=>[ye(" I don't need MFA "),bq]),_:1}))])])])],8,tq)}const xq=ze(eq,[["render",wq]]),kq={name:"share",async setup(){const e=tP(),t=be(!1),n=et(),s=be(""),i=be(""),o=be(new Blob);await $t("/api/getDashboardTheme",{},a=>{s.value=a.data});const r=e.query.ShareID;return r===void 0||r.length===0?(i.value=void 0,t.value=!0):await $t("/api/sharePeer/get",{ShareID:r},a=>{a.status?(i.value=a.data,o.value=new Blob([i.value.file],{type:"text/plain"})):i.value=void 0,t.value=!0}),{store:n,theme:s,peerConfiguration:i,blob:o}},mounted(){Bo.toCanvas(document.querySelector("#qrcode"),this.peerConfiguration.file,e=>{e&&console.error(e)})},methods:{download(){const e=new Blob([this.peerConfiguration.file],{type:"text/plain"}),t=URL.createObjectURL(e),n=`${this.peerConfiguration.fileName}.conf`,s=document.createElement("a");s.href=t,s.download=n,s.click()}},computed:{getBlob(){return URL.createObjectURL(this.blob)}}},hp=e=>(Kt("data-v-99d4b06a"),e=e(),qt(),e),Sq=["data-bs-theme"],$q={class:"m-auto text-body",style:{width:"500px"}},Aq={key:0,class:"text-center position-relative",style:{}},Cq=QA('Oh no... This link is either expired or invalid.
+ {{Peer.name ? Peer.name : 'Untitled Peer'}}
+
+
+
+
+
+
+ Add Peers
+
+
+ Schedule Jobs
+
+
+
+