diff --git a/.env.example b/.env.example index 6673f8ea8..b2dcabb16 100644 --- a/.env.example +++ b/.env.example @@ -119,6 +119,8 @@ LNBITS_SITE_TAGLINE="Open Source Lightning Payments Platform" LNBITS_SITE_DESCRIPTION="The world's most powerful suite of bitcoin tools. Run for yourself, for others, or as part of a stack." # Choose from bitcoin, mint, flamingo, freedom, salvador, autumn, monochrome, classic, cyber LNBITS_THEME_OPTIONS="classic, bitcoin, flamingo, freedom, mint, autumn, monochrome, salvador, cyber" +# Toggle the background styling on burger menus / drawers +# LNBITS_DEFAULT_BURGER_MENU_BACKGROUND=true # LNBITS_CUSTOM_LOGO="https://lnbits.com/assets/images/logo/logo.svg" ###################################### diff --git a/lnbits/settings.py b/lnbits/settings.py index 475201139..4923e8bf5 100644 --- a/lnbits/settings.py +++ b/lnbits/settings.py @@ -300,6 +300,7 @@ class ThemesSettings(LNbitsSettings): lnbits_default_card_rounded: bool = Field(default=True) lnbits_default_card_gradient: bool = Field(default=True) lnbits_default_card_shadow: bool = Field(default=False) + lnbits_default_burger_menu_background: bool = Field(default=True) class OpsSettings(LNbitsSettings): @@ -1281,6 +1282,7 @@ class PublicSettings(BaseModel): default_card_rounded: bool = Field(alias="defaultCardRounded") default_card_gradient: bool = Field(alias="defaultCardGradient") default_card_shadow: bool = Field(alias="defaultCardShadow") + default_burger_menu_background: bool = Field(alias="defaultBurgerMenuBackground") denomination: str | None = Field() extensions: list[str] = Field() allowed_currencies: list[str] = Field(alias="allowedCurrencies") @@ -1344,6 +1346,7 @@ class PublicSettings(BaseModel): defaultCardRounded=settings.lnbits_default_card_rounded, defaultCardGradient=settings.lnbits_default_card_gradient, defaultCardShadow=settings.lnbits_default_card_shadow, + defaultBurgerMenuBackground=settings.lnbits_default_burger_menu_background, denomination=settings.lnbits_denomination, extensions=list(settings.lnbits_installed_extensions_ids), allowedCurrencies=settings.lnbits_allowed_currencies, diff --git a/lnbits/static/bundle-components.min.js b/lnbits/static/bundle-components.min.js index ab71a4ae8..e57fe7269 100644 --- a/lnbits/static/bundle-components.min.js +++ b/lnbits/static/bundle-components.min.js @@ -1 +1 @@ -window.PageError={template:"#page-error"},window.PageHome={template:"#page-home",data:()=>({lnurl:"",authAction:"login",authMethod:"username-password",usr:"",username:"",reset_key:"",email:"",password:"",passwordRepeat:"",invitationCode:"",walletName:"",signup:!1}),computed:{showClaimLnurl(){return""!==this.lnurl&&this.g.settings.allowRegister&&this.g.settings.authMethods.includes("user-id-only")},formatDescription(){return LNbits.utils.convertMarkdown(this.g.settings.siteDescription)},isAccessTokenExpired(){return this.$q.cookies.get("is_access_token_expired")}},methods:{showLogin(e){this.authAction="login",this.authMethod=e},showRegister(e){this.user="",this.username=null,this.password=null,this.passwordRepeat=null,this.invitationCode=null,this.authAction="register",this.authMethod=e},async register(){try{await LNbits.api.register(this.username,this.email,this.password,this.passwordRepeat,this.invitationCode),this.refreshAuthUser()}catch(e){LNbits.utils.notifyApiError(e)}},async reset(){try{await LNbits.api.reset(this.reset_key,this.password,this.passwordRepeat),this.refreshAuthUser()}catch(e){LNbits.utils.notifyApiError(e)}},async login(){try{await LNbits.api.login(this.username,this.password),this.refreshAuthUser()}catch(e){LNbits.utils.notifyApiError(e)}},async loginUsr(){try{await LNbits.api.loginUsr(this.usr),this.refreshAuthUser()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async refreshAuthUser(){try{const e=await LNbits.api.getAuthUser();this.g.user=LNbits.map.user(e.data),this.g.isPublicPage=!1,this.$router.push(`/wallet/${this.g.user.wallets[0].id}`)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},createWallet(){LNbits.api.createAccount(this.walletName).then(e=>{this.$router.push(`/wallet/${e.data.id}`)})},processing(){Quasar.Notify.create({timeout:0,message:"Processing...",icon:null})}},created(){if(this.g.isUserAuthorized)return this.refreshAuthUser();const e=new URLSearchParams(window.location.search);this.reset_key=e.get("reset_key"),this.reset_key&&(this.authAction="reset"),e.has("lightning")&&(this.lnurl=e.get("lightning"))}},window.PageExtensionBuilder={template:"#page-extension-builder",data:()=>({step:1,previewStepNames:{2:"settings",3:"owner_data",4:"client_data",5:"public_page"},extensionDataCleanString:"",extensionData:{id:"",name:"",stub_version:"",short_description:"",description:"",public_page:{has_public_page:!0,owner_data_fields:{name:"",description:""},client_data_fields:{public_inputs:[]},action_fields:{generate_action:!0,generate_payment_logic:!1,wallet_id:"",currency:"",amount:"",paid_flag:""}},preview_action:{is_preview_mode:!1,is_settings_preview:!1,is_owner_data_preview:!1,is_client_data_preview:!1,is_public_page_preview:!1},settings_data:{name:"Settings",enabled:!0,type:"user",fields:[]},owner_data:{name:"OwnerData",fields:[]},client_data:{enabled:!0,name:"ClientData",fields:[]}},sampleField:{name:"name",type:"str",label:"Name",hint:"",optional:!0,editable:!0,searchable:!0,sortable:!0},settingsTypes:[{label:"User Settings",value:"user"},{label:"Admin Settings",value:"admin"}],amountSource:[{label:"Client Data",value:"client_data"},{label:"Owner Data",value:"owner_data"}],extensionStubVersions:[]}),watch:{"extensionData.public_page.action_fields.amount_source":function(e,t){t&&e!==t&&(this.extensionData.public_page.action_fields.amount="")}},computed:{paymentActionAmountFields(){const e=this.extensionData.public_page.action_fields.amount_source;return e?"owner_data"===e?[""].concat(this.extensionData.owner_data.fields.filter(e=>"int"===e.type||"float"===e.type).map(e=>e.name)):"client_data"===e?[""].concat(this.extensionData.client_data.fields.filter(e=>"int"===e.type||"float"===e.type).map(e=>e.name)):void 0:[""]}},methods:{saveState(){this.$q.localStorage.set("lnbits.extension.builder.data",JSON.stringify(this.extensionData)),this.$q.localStorage.set("lnbits.extension.builder.step",this.step)},nextStep(){this.saveState(),this.$refs.stepper.next(),this.refreshPreview()},previousStep(){this.saveState(),this.$refs.stepper.previous(),this.refreshPreview()},onStepChange(){this.saveState(),this.refreshPreview()},clearAllData(){LNbits.utils.confirmDialog("Are you sure you want to clear all data? This action cannot be undone.").onOk(()=>{this.extensionData=JSON.parse(this.extensionDataCleanString),this.$q.localStorage.remove("lnbits.extension.builder.data"),this.$refs.stepper.set(1)})},exportJsonData(){!0!==Quasar.exportFile(`${this.extensionData.id||"data-export"}.json`,JSON.stringify(this.extensionData,null,2),"text/json")?Quasar.Notify.create({message:"Browser denied file download...",color:"negative",icon:null}):Quasar.Notify.create({message:"File downloaded!",color:"positive",icon:"file_download"})},onJsonDataInput(e){const t=e.target.files[0],a=new FileReader;a.onload=e=>{this.extensionData={...this.extensionData,...JSON.parse(e.target.result)},this.$refs.extensionDataInput.value=null,Quasar.Notify.create({message:"File loaded!",color:"positive",icon:"file_upload"})},a.readAsText(t)},async buildExtension(){try{const e={responseType:"blob"},t=await LNbits.api.request("POST","/api/v1/extension/builder/zip",null,this.extensionData,e),a=window.URL.createObjectURL(new Blob([t.data])),s=document.createElement("a");s.href=a,s.download=`${this.extensionData.id||"lnbits-extension"}.zip`,document.body.appendChild(s),s.click(),s.remove(),window.URL.revokeObjectURL(a)}catch(e){LNbits.utils.notifyApiError(e)}},async buildExtensionAndDeploy(){try{const{data:e}=await LNbits.api.request("POST","/api/v1/extension/builder/deploy",null,this.extensionData);Quasar.Notify.create({message:e.message||"Extension deployed!",color:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}},async cleanCacheData(){LNbits.utils.confirmDialog("Are you sure you want to clean the cache data? This action cannot be undone.","Clean Cache Data").onOk(async()=>{try{const{data:e}=await LNbits.api.request("DELETE","/api/v1/extension/builder",null,{});Quasar.Notify.create({message:e.message||"Cache data cleaned!",color:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}})},async previewExtension(e){this.saveState();try{await LNbits.api.request("POST","/api/v1/extension/builder/preview",null,{...this.extensionData,preview_action:{is_preview_mode:!!e,is_settings_preview:"settings"===e,is_owner_data_preview:"owner_data"===e,is_client_data_preview:"client_data"===e,is_public_page_preview:"public_page"===e}}),this.refreshIframe(e)}catch(e){LNbits.utils.notifyApiError(e)}},async refreshPreview(){setTimeout(()=>{const e=this.previewStepNames[`${this.step}`]||"";e&&this.previewExtension(e)},100)},async getStubExtensionReleases(){try{const e="extension_builder_stub",{data:t}=await LNbits.api.request("GET",`/api/v1/extension/${e}/releases`);this.extensionStubVersions=t;const a=t.filter(e=>e.is_version_compatible);this.extensionData.stub_version=a[0]?a[0].version:""}catch(e){LNbits.utils.notifyApiError(e)}},refreshIframe(e=""){const t=this.$refs[`iframeStep${this.step}`];if(!t)return void console.warn("Extension Builder Preview iframe not loaded yet.");t.onload=()=>{const e=t.contentDocument||t.contentWindow.document;e.body.style.transform="scale(0.8)",e.body.style.transformOrigin="center top"};let a="Page"+this.extensionData.id.toLowerCase().split("_").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("");"public_page"===e&&(a+="Public"),t.src=`/extensions/builder/preview?ext_id=${this.extensionData.id}&page=${e}&component=${a}`},initBasicData(){this.extensionData.owner_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionData.client_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionData.settings_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionDataCleanString=JSON.stringify(this.extensionData)}},created(){this.initBasicData();const e=this.$q.localStorage.getItem("lnbits.extension.builder.data");e&&(this.extensionData={...this.extensionData,...JSON.parse(e)});const t=+this.$q.localStorage.getItem("lnbits.extension.builder.step");t&&(this.step=t),this.g.user.admin&&this.getStubExtensionReleases(),setTimeout(()=>{this.refreshIframe()},1e3)}},window.PageExtensionBuilder={template:"#page-extension-builder",data:()=>({step:1,previewStepNames:{2:"settings",3:"owner_data",4:"client_data",5:"public_page"},extensionDataCleanString:"",extensionData:{id:"",name:"",stub_version:"",short_description:"",description:"",public_page:{has_public_page:!0,owner_data_fields:{name:"",description:""},client_data_fields:{public_inputs:[]},action_fields:{generate_action:!0,generate_payment_logic:!1,wallet_id:"",currency:"",amount:"",paid_flag:""}},preview_action:{is_preview_mode:!1,is_settings_preview:!1,is_owner_data_preview:!1,is_client_data_preview:!1,is_public_page_preview:!1},settings_data:{name:"Settings",enabled:!0,type:"user",fields:[]},owner_data:{name:"OwnerData",fields:[]},client_data:{enabled:!0,name:"ClientData",fields:[]}},sampleField:{name:"name",type:"str",label:"Name",hint:"",optional:!0,editable:!0,searchable:!0,sortable:!0},settingsTypes:[{label:"User Settings",value:"user"},{label:"Admin Settings",value:"admin"}],amountSource:[{label:"Client Data",value:"client_data"},{label:"Owner Data",value:"owner_data"}],extensionStubVersions:[]}),watch:{"extensionData.public_page.action_fields.amount_source":function(e,t){t&&e!==t&&(this.extensionData.public_page.action_fields.amount="")}},computed:{paymentActionAmountFields(){const e=this.extensionData.public_page.action_fields.amount_source;return e?"owner_data"===e?[""].concat(this.extensionData.owner_data.fields.filter(e=>"int"===e.type||"float"===e.type).map(e=>e.name)):"client_data"===e?[""].concat(this.extensionData.client_data.fields.filter(e=>"int"===e.type||"float"===e.type).map(e=>e.name)):void 0:[""]}},methods:{saveState(){this.$q.localStorage.set("lnbits.extension.builder.data",JSON.stringify(this.extensionData)),this.$q.localStorage.set("lnbits.extension.builder.step",this.step)},nextStep(){this.saveState(),this.$refs.stepper.next(),this.refreshPreview()},previousStep(){this.saveState(),this.$refs.stepper.previous(),this.refreshPreview()},onStepChange(){this.saveState(),this.refreshPreview()},clearAllData(){LNbits.utils.confirmDialog("Are you sure you want to clear all data? This action cannot be undone.").onOk(()=>{this.extensionData=JSON.parse(this.extensionDataCleanString),this.$q.localStorage.remove("lnbits.extension.builder.data"),this.$refs.stepper.set(1)})},exportJsonData(){!0!==Quasar.exportFile(`${this.extensionData.id||"data-export"}.json`,JSON.stringify(this.extensionData,null,2),"text/json")?Quasar.Notify.create({message:"Browser denied file download...",color:"negative",icon:null}):Quasar.Notify.create({message:"File downloaded!",color:"positive",icon:"file_download"})},onJsonDataInput(e){const t=e.target.files[0],a=new FileReader;a.onload=e=>{this.extensionData={...this.extensionData,...JSON.parse(e.target.result)},this.$refs.extensionDataInput.value=null,Quasar.Notify.create({message:"File loaded!",color:"positive",icon:"file_upload"})},a.readAsText(t)},async buildExtension(){try{const e={responseType:"blob"},t=await LNbits.api.request("POST","/api/v1/extension/builder/zip",null,this.extensionData,e),a=window.URL.createObjectURL(new Blob([t.data])),s=document.createElement("a");s.href=a,s.download=`${this.extensionData.id||"lnbits-extension"}.zip`,document.body.appendChild(s),s.click(),s.remove(),window.URL.revokeObjectURL(a)}catch(e){LNbits.utils.notifyApiError(e)}},async buildExtensionAndDeploy(){try{const{data:e}=await LNbits.api.request("POST","/api/v1/extension/builder/deploy",null,this.extensionData);Quasar.Notify.create({message:e.message||"Extension deployed!",color:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}},async cleanCacheData(){LNbits.utils.confirmDialog("Are you sure you want to clean the cache data? This action cannot be undone.","Clean Cache Data").onOk(async()=>{try{const{data:e}=await LNbits.api.request("DELETE","/api/v1/extension/builder",null,{});Quasar.Notify.create({message:e.message||"Cache data cleaned!",color:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}})},async previewExtension(e){this.saveState();try{await LNbits.api.request("POST","/api/v1/extension/builder/preview",null,{...this.extensionData,preview_action:{is_preview_mode:!!e,is_settings_preview:"settings"===e,is_owner_data_preview:"owner_data"===e,is_client_data_preview:"client_data"===e,is_public_page_preview:"public_page"===e}}),this.refreshIframe(e)}catch(e){LNbits.utils.notifyApiError(e)}},async refreshPreview(){setTimeout(()=>{const e=this.previewStepNames[`${this.step}`]||"";e&&this.previewExtension(e)},100)},async getStubExtensionReleases(){try{const e="extension_builder_stub",{data:t}=await LNbits.api.request("GET",`/api/v1/extension/${e}/releases`);this.extensionStubVersions=t;const a=t.filter(e=>e.is_version_compatible);this.extensionData.stub_version=a[0]?a[0].version:""}catch(e){LNbits.utils.notifyApiError(e)}},refreshIframe(e=""){const t=this.$refs[`iframeStep${this.step}`];if(!t)return void console.warn("Extension Builder Preview iframe not loaded yet.");t.onload=()=>{const e=t.contentDocument||t.contentWindow.document;e.body.style.transform="scale(0.8)",e.body.style.transformOrigin="center top"};let a="Page"+this.extensionData.id.toLowerCase().split("_").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("");"public_page"===e&&(a+="Public"),t.src=`/extensions/builder/preview?ext_id=${this.extensionData.id}&page=${e}&component=${a}`},initBasicData(){this.extensionData.owner_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionData.client_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionData.settings_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionDataCleanString=JSON.stringify(this.extensionData)}},created(){this.initBasicData();const e=this.$q.localStorage.getItem("lnbits.extension.builder.data");e&&(this.extensionData={...this.extensionData,...JSON.parse(e)});const t=+this.$q.localStorage.getItem("lnbits.extension.builder.step");t&&(this.step=t),this.g.user.admin&&this.getStubExtensionReleases(),setTimeout(()=>{this.refreshIframe()},1e3)}},window.PageExtensionBuilderPreview={template:"#page-extension-builder-preview",mixins:[windowMixin],watch:{name:"reload"},data:()=>({extId:"",pageName:"",componentName:null}),methods:{async reload(){await LNbits.utils.loadTemplate(`/extensions/builder/preview/${this.extId}/template?page_name=${this.pageName}`),await LNbits.utils.loadScript(`/extensions/builder/preview/${this.extId}/component?page_name=${this.pageName}`),this._component=window[this.componentName],console.log("LNbits preview reloaded componentName:",this.componentName,!!this._component),this.$forceUpdate()}},async created(){const e=new URLSearchParams(window.location.search);this.extId=e.get("ext_id")||"",this.pageName=e.get("page")||"",this.componentName=e.get("component")||"",await this.reload()},render(){return this._component?Vue.h(this._component):Vue.h("div","Loading...")}},window.PageExtensions={template:"#page-extensions",data(){return{extbuilderEnabled:!1,slide:0,fullscreen:!1,autoplay:!0,searchTerm:"",tab:"installed",manageExtensionTab:"releases",filteredExtensions:[],updatableExtensions:[],showUninstallDialog:!1,showManageExtensionDialog:!1,showExtensionDetailsDialog:!1,showDropDbDialog:!1,showPayToEnableDialog:!1,showUpdateAllDialog:!1,dropDbExtensionId:"",selectedExtension:null,selectedImage:null,selectedExtensionDetails:null,selectedExtensionRepos:null,selectedRelease:null,uninstallAndDropDb:!1,maxStars:5,paylinkWebsocket:null,searchToggle:!1,reviewsUrl:null,reviewsDialog:{show:!1,extension:null,loading:!1,submitting:!1,form:{name:"",rating:0,comment:""},error:null},reviews:[],reviewsTable:{loading:!1,columns:[{name:"name",align:"left",label:this.$t("Name"),field:"name",sortable:!0},{name:"comment",align:"left",label:this.$t("Comment"),field:"comment"},{name:"created_at",align:"left",label:this.$t("Date"),field:"created_at"},{name:"rating",align:"right",label:"Rating",field:"rating"}],pagination:{rowsPerPage:5,sortBy:"created_at",descending:!0,page:1}},paymentDialog:{show:!1,invoice:"",hash:""}}},watch:{searchTerm(e){this.filterExtensions(e,this.tab)},tab(e){this.filterExtensions(this.searchTerm,e)}},methods:{filterExtensions(e,t){var a;this.filteredExtensions=this.extensions.filter(e=>"all"!==t||!e.isInstalled).filter(e=>"installed"!==t||e.isInstalled).filter(e=>"installed"!==t||(!!e.isActive||!!this.g.user.admin)).filter(e=>"featured"!==t||e.isFeatured).filter((a=e,function(e){return e.name.toLowerCase().includes(a.toLowerCase())||e.shortDescription?.toLowerCase().includes(a.toLowerCase())})).map(e=>({...e,details_link:e.installedRelease?.details_link||e.latestRelease?.details_link}))},async installExtension(e){this.unsubscribeFromPaylinkWs(),this.selectedExtension.inProgress=!0,this.showManageExtensionDialog=!1,e.payment_hash=e.payment_hash||this.getPaylinkHash(e.pay_link),LNbits.api.request("POST","/api/v1/extension",this.g.user.wallets[0].adminkey,{ext_id:this.selectedExtension.id,archive:e.archive,source_repo:e.source_repo,payment_hash:e.payment_hash,version:e.version}).then(t=>{this.selectedExtension.inProgress=!1;const a=this.extensions.find(e=>e.id===this.selectedExtension.id);a.isAvailable=!0,a.isInstalled=!0,a.installedRelease=e,this.toggleExtension(a),a.inProgress=!1,this.selectedExtension=a,this.extensions=this.extensions.concat([]),this.tab="installed"}).catch(e=>{console.warn(e),this.selectedExtension.inProgress=!1,LNbits.utils.notifyApiError(e)})},async uninstallExtension(){this.showManageExtensionDialog=!1,this.showUninstallDialog=!1,this.selectedExtension.inProgress=!0,LNbits.api.request("DELETE",`/api/v1/extension/${this.selectedExtension.id}`,this.g.user.wallets[0].adminkey).then(e=>{const t=this.extensions.find(e=>e.id===this.selectedExtension.id);t.isAvailable=!1,t.isInstalled=!1,t.inProgress=!1,t.installedRelease=null,this.filteredExtensions=this.filteredExtensions.filter(e=>e.id!==t.id),Quasar.Notify.create({type:"positive",message:"Extension uninstalled!"}),this.uninstallAndDropDb&&this.showDropDb()}).catch(e=>{LNbits.utils.notifyApiError(e),extension.inProgress=!1})},async dropExtensionDb(){const e=this.selectedExtension;this.showManageExtensionDialog=!1,this.showDropDbDialog=!1,this.dropDbExtensionId="",e.inProgress=!0,LNbits.api.request("DELETE",`/api/v1/extension/${e.id}/db`,this.g.user.wallets[0].adminkey).then(t=>{e.installedRelease=null,e.inProgress=!1,e.hasDatabaseTables=!1,Quasar.Notify.create({type:"positive",message:"Extension DB deleted!"})}).catch(t=>{LNbits.utils.notifyApiError(t),e.inProgress=!1})},toggleExtension(e){const t=e.isActive?"activate":"deactivate";LNbits.api.request("PUT",`/api/v1/extension/${e.id}/${t}`,this.g.user.wallets[0].adminkey).then(a=>{Quasar.Notify.create({timeout:2e3,type:"positive",message:`Extension '${e.id}' ${t}d!`})}).catch(t=>{LNbits.utils.notifyApiError(t),e.isActive=!1,e.inProgress=!1})},async enableExtensionForUser(e){e.isPaymentRequired?this.showPayToEnable(e):this.enableExtension(e)},async enableExtension(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/enable`,this.g.user.wallets[0].adminkey).then(t=>{this.g.user.extensions=this.g.user.extensions.concat([e.id]),Quasar.Notify.create({type:"positive",message:"Extension enabled!"})}).catch(e=>{console.warn(e),LNbits.utils.notifyApiError(e)})},disableExtension(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/disable`,this.g.user.wallets[0].adminkey).then(t=>{this.g.user.extensions=this.g.user.extensions.filter(t=>t!==e.id),Quasar.Notify.create({type:"positive",message:"Extension disabled!"})}).catch(e=>{console.warn(error),LNbits.utils.notifyApiError(e)})},showPayToEnable(e){this.selectedExtension=e,this.selectedExtension.payToEnable.paidAmount=e.payToEnable.amount,this.selectedExtension.payToEnable.showQRCode=!1,this.showPayToEnableDialog=!0},updatePayToInstallData(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/sell`,this.g.user.wallets[0].adminkey,{required:e.payToEnable.required,amount:e.payToEnable.amount,wallet:e.payToEnable.wallet}).then(e=>{Quasar.Notify.create({type:"positive",message:"Payment info updated!"}),this.showManageExtensionDialog=!1}).catch(t=>{LNbits.utils.notifyApiError(t),e.inProgress=!1})},showUninstall(){this.showManageExtensionDialog=!1,this.showUninstallDialog=!0,this.uninstallAndDropDb=!1},showDropDb(){this.showDropDbDialog=!0},async showManageExtension(e){this.selectedExtension=e,this.selectedRelease=null,this.selectedExtensionRepos=null,this.manageExtensionTab="releases",this.showManageExtensionDialog=!0;try{const{data:t}=await LNbits.api.request("GET",`/api/v1/extension/${e.id}/releases`);this.selectedExtensionRepos=t.reduce((e,t)=>(e[t.source_repo]=e[t.source_repo]||{releases:[],isInstalled:!1,repo:t.repo},t.inProgress=!1,t.error=null,t.loaded=!1,t.isInstalled=this.isInstalledVersion(this.selectedExtension,t),t.isInstalled&&(e[t.source_repo].isInstalled=!0),t.pay_link&&(t.requiresPayment=!0,t.paidAmount=t.cost_sats,t.payment_hash=this.getPaylinkHash(t.pay_link)),e[t.source_repo].releases.push(t),e),{})}catch(t){LNbits.utils.notifyApiError(t),e.inProgress=!1}},async showExtensionDetails(e,t){if(t){this.selectedExtension=this.extensions.find(t=>t.id===e)||this.selectedExtension,this.selectedExtensionDetails=null,this.showExtensionDetailsDialog=!0,this.slide=0,this.fullscreen=!1;try{const{data:a}=await LNbits.api.request("GET",`/api/v1/extension/${e}/details?details_link=${t}`);this.selectedExtensionDetails=a,this.selectedExtensionDetails.description_md=LNbits.utils.convertMarkdown(a.description_md)}catch(e){console.warn(e)}}},async payAndInstall(e){try{this.selectedExtension.inProgress=!0,this.showManageExtensionDialog=!1;const t=await this.requestPaymentForInstall(this.selectedExtension.id,e);this.rememberPaylinkHash(e.pay_link,t.payment_hash);const a=this.g.user.wallets.find(t=>t.id===e.wallet),{data:s}=await LNbits.api.payInvoice(a,t.payment_request);e.payment_hash=s.payment_hash,await this.installExtension(e)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}finally{this.selectedExtension.inProgress=!1}},async payAndEnable(e){try{const t=await this.requestPaymentForEnable(e.id,e.payToEnable.paidAmount),a=this.g.user.wallets.find(t=>t.id===e.payToEnable.paymentWallet),{data:s}=await LNbits.api.payInvoice(a,t.payment_request);this.enableExtension(e),this.showPayToEnableDialog=!1}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async showInstallQRCode(e){this.selectedRelease=e;try{const t=await this.requestPaymentForInstall(this.selectedExtension.id,e);this.selectedRelease.paymentRequest=t.payment_request,this.selectedRelease.payment_hash=t.payment_hash,this.selectedRelease=_.clone(this.selectedRelease),this.rememberPaylinkHash(this.selectedRelease.pay_link,this.selectedRelease.payment_hash),this.subscribeToPaylinkWs(this.selectedRelease.pay_link,t.payment_hash)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async showEnableQRCode(e){try{e.payToEnable.showQRCode=!0,this.selectedExtension=_.clone(e);const t=await this.requestPaymentForEnable(e.id,e.payToEnable.paidAmount);e.payToEnable.paymentRequest=t.payment_request,this.selectedExtension=_.clone(e);const a=new URL(window.location);a.protocol="https:"===a.protocol?"wss":"ws",a.pathname=`/api/v1/ws/${t.payment_hash}`;const s=new WebSocket(a);s.addEventListener("message",async({data:t})=>{!1===JSON.parse(t).pending&&(Quasar.Notify.create({type:"positive",message:"Invoice Paid!"}),this.enableExtension(e),s.close())})}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async requestPaymentForInstall(e,t){const{data:a}=await LNbits.api.request("PUT",`/api/v1/extension/${e}/invoice/install`,null,{ext_id:e,archive:t.archive,source_repo:t.source_repo,cost_sats:t.paidAmount,version:t.version});return a},async requestPaymentForEnable(e,t){const{data:a}=await LNbits.api.request("PUT",`/api/v1/extension/${e}/invoice/enable`,null,{amount:t});return a},clearHangingInvoice(e){this.forgetPaylinkHash(e.pay_link),e.payment_hash=null},rememberPaylinkHash(e,t){this.$q.localStorage.set(`lnbits.extensions.paylink.${e}`,t)},getPaylinkHash(e){return this.$q.localStorage.getItem(`lnbits.extensions.paylink.${e}`)},forgetPaylinkHash(e){this.$q.localStorage.remove(`lnbits.extensions.paylink.${e}`)},subscribeToPaylinkWs(e,t){const a=new URL(`${e}/${t}`);a.protocol="https:"===a.protocol?"wss":"ws",this.paylinkWebsocket=new WebSocket(a),this.paylinkWebsocket.addEventListener("message",async({data:e})=>{JSON.parse(e).paid?(Quasar.Notify.create({type:"positive",message:"Invoice Paid!"}),this.installExtension(this.selectedRelease)):Quasar.Notify.create({type:"warning",message:"Invoice tracking lost!"})})},unsubscribeFromPaylinkWs(){try{this.paylinkWebsocket&&this.paylinkWebsocket.close()}catch(e){console.warn(e)}},hasNewVersion(e){if(e.installedRelease&&e.latestRelease)return e.installedRelease.version!==e.latestRelease.version},isInstalledVersion(e,t){if(e.installedRelease)return e.installedRelease.source_repo===t.source_repo&&e.installedRelease.version===t.version},getReleaseIcon:e=>e.is_version_compatible?e.isInstalled?"download_done":"download":"block",getReleaseIconColor:e=>e.is_version_compatible?e.isInstalled?"text-green":"":"text-red",async getGitHubReleaseDetails(e){if(!e.is_github_release||e.loaded)return;const[t,a]=e.source_repo.split("/");e.inProgress=!0;try{const{data:s}=await LNbits.api.request("GET",`/api/v1/extension/release/${t}/${a}/${e.version}`);e.loaded=!0,e.is_version_compatible=s.is_version_compatible,e.min_lnbits_version=s.min_lnbits_version,e.warning=s.warning}catch(t){console.warn(t),e.error=t,LNbits.utils.notifyApiError(t)}finally{e.inProgress=!1}},async selectAllUpdatableExtensionss(){this.updatableExtensions.forEach(e=>e.selectedForUpdate=!0)},async updateSelectedExtensions(){let e=0;for(const t of this.updatableExtensions)try{if(!t.selectedForUpdate)continue;t.inProgress=!0,await LNbits.api.request("POST","/api/v1/extension",null,{ext_id:t.id,archive:t.latestRelease.archive,source_repo:t.latestRelease.source_repo,payment_hash:t.latestRelease.payment_hash,version:t.latestRelease.version}),e++,t.isAvailable=!0,t.isInstalled=!0,t.isUpgraded=!0,t.inProgress=!1,t.installedRelease=t.latestRelease,t.isActive=!0,this.toggleExtension(t)}catch(e){console.warn(e),Quasar.Notify.create({type:"negative",message:`Failed to update ${t.id}!`})}finally{t.inProgress=!1}Quasar.Notify.create({type:e?"positive":"warning",message:`${e||"No"} extensions updated!`}),this.showUpdateAllDialog=!1},formatAvg(e){const t=Number(e||0);return Math.round(t/2/100*2)/2},async loadReviewStats(){if(this.reviewsUrl)try{const{data:e}=await LNbits.api.request("GET","/api/v1/extension/reviews/tags"),t={};e.forEach(e=>{t[e.tag]=e}),this.extensions.forEach(e=>{e.reviewStats=t[e.id]||null}),this.filterExtensions(this.searchTerm,this.tab)}catch(e){console.warn(e)}else console.info("Extension reviews are not configured")},async openReviews(e){const t=e||(this.selectedExtensionDetails?this.extensions.find(e=>e.id===this.selectedExtensionDetails.id):null);t&&(this.reviewsUrl?(this.reviewsDialog.extension=t,this.selectedExtension=e,this.reviewsDialog.show=!0,await this.getTagReviews()):Quasar.Notify.create({type:"warning",message:this.$t("reviews_url_not_configured")}))},async getTagReviews(e){if(this.reviewsUrl)try{this.reviewsTable.loading=!0;const t=LNbits.utils.prepareFilterQuery(this.reviewsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/extension/reviews/${this.selectedExtension.id}?${t}`);this.reviews=a.data,this.reviewsTable.pagination.rowsNumber=a.total}catch(e){LNbits.utils.notifyApiError(e)}finally{this.reviewsTable.loading=!1}else Quasar.Notify.create({type:"warning",message:this.$t("reviews_url_not_configured")})},formatReviewDate(e){if(!e)return"";const t=Number(e);return Number.isNaN(t)?this.utils.formatDate(e):this.utils.formatTimestamp(t)},async submitReview(){if(this.reviewsDialog.extension&&this.reviewsUrl){this.reviewsDialog.submitting=!0;try{const e={tag:this.reviewsDialog.extension.id,name:this.reviewsDialog.form.name,rating:100*this.reviewsDialog.form.rating,comment:this.reviewsDialog.form.comment},{data:t}=await LNbits.api.request("PUT","/api/v1/extension/reviews",null,e);t.payment_request?this.openInvoiceDialog(t.payment_request,t.payment_hash):(Quasar.Notify.create({type:"positive",message:"Review submitted"}),this.resetReviewForm(),await this.getTagReviews(),await this.loadReviewStats())}catch(e){LNbits.utils.notifyApiError(e)}finally{this.reviewsDialog.submitting=!1}}},openInvoiceDialog(e,t){this.paymentDialog.invoice=e,this.paymentDialog.hash=t,this.paymentDialog.show=!0,this.listenForPayment(t)},resetReviewForm(){this.reviewsDialog.form={name:"",rating:0,comment:""},this.paymentDialog={show:!1,invoice:"",hash:""}},listenForPayment(e){try{const t=new URL(this.reviewsUrl);t.protocol="https:"===t.protocol?"wss:":"ws:",t.pathname=`/api/v1/ws/${e}`;const a=new WebSocket(t);a.addEventListener("message",async()=>{Quasar.Notify.create({type:"positive",message:this.$t("reviews_invoice_paid")}),this.paymentDialog.show=!1,this.resetReviewForm(),setTimeout(async()=>{await this.getTagReviews()},1e3),await this.loadReviewStats(),a.close()})}catch(e){console.warn(e)}},async fetchAllExtensions(){try{const{data:e}=await LNbits.api.request("GET","/api/v1/extension/all");return e}catch(e){return console.warn(e),LNbits.utils.notifyApiError(e),[]}}},async created(){this.extensions=await this.fetchAllExtensions(),this.extbuilderEnabled=this.g.user.admin||this.g.settings.extBuilder,this.reviewsUrl=this.g.settings.extensionsReviewsUrl,0===this.g.user.extensions.length&&(this.tab="all");const e=window.location.hash.replace("#",""),t=this.extensions.find(t=>t.id===e);t&&(this.searchTerm=t.id,t.isInstalled&&(this.tab="installed")),this.updatableExtensions=this.extensions.filter(e=>this.hasNewVersion(e)),await this.loadReviewStats(),this.filterExtensions(this.searchTerm,this.tab)}},window.PageFirstInstall={template:"#page-first-install",data:()=>({loginData:{isPwd:!0,isPwdRepeat:!0,username:"",password:"",passwordRepeat:"",firstInstallToken:""}}),computed:{checkPasswordsMatch(){return this.loginData.password!==this.loginData.passwordRepeat}},methods:{setPassword(){LNbits.api.request("PUT","/api/v1/auth/first_install",null,{username:this.loginData.username,password:this.loginData.password,password_repeat:this.loginData.passwordRepeat,first_install_token:this.loginData.firstInstallToken}).then(async()=>{const e=await LNbits.api.getAuthUser();this.g.user=LNbits.map.user(e.data),this.g.isPublicPage=!1,this.$router.push("/admin")}).catch(this.utils.notifyApiError)}},created(){const e=new URLSearchParams(window.location.search);this.loginData.firstInstallToken=e.get("token")||""}},window.PagePayments={template:"#page-payments",data:()=>({payments:[],dailyChartData:[],searchDate:{from:null,to:null},searchData:{wallet_id:null,payment_hash:null,memo:null,internal_memo:null},statusFilters:{success:!0,pending:!0,failed:!0,incoming:!0,outgoing:!0},chartData:{showPaymentStatus:!0,showPaymentTags:!0,showBalance:!0,showWalletsSize:!1,showBalanceInOut:!1,showPaymentCountInOut:!1},searchOptions:{status:[]},paymentsTable:{columns:[{name:"status",align:"left",label:"Status",field:"status",sortable:!1},{name:"created_at",align:"left",label:"Created At",field:"created_at",sortable:!0},{name:"amount",align:"right",label:"Amount",field:"amount",sortable:!0},{name:"amountFiat",align:"right",label:"Fiat",field:"amountFiat",sortable:!1},{name:"fee_sats",align:"left",label:"Fee",field:"fee_sats",sortable:!0},{name:"tag",align:"left",label:"Tag",field:"tag",sortable:!1},{name:"memo",align:"left",label:"Memo",field:"memo",sortable:!1,max_length:20},{name:"internal_memo",align:"left",label:"Internal Memo",field:"internal_memo",sortable:!1,max_length:20},{name:"wallet_id",align:"left",label:"Wallet (ID)",field:"wallet_id",sortable:!1},{name:"payment_hash",align:"left",label:"Payment Hash",field:"payment_hash",sortable:!1}],pagination:{sortBy:"created_at",rowsPerPage:25,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},chartsReady:!1,showDetails:!1,paymentDetails:null,lnbitsBalance:0}),async mounted(){this.chartsReady=!0,await this.$nextTick(),this.initCharts(),await this.fetchPayments()},computed:{},methods:{async fetchPayments(e){const t=Object.entries(this.searchData).reduce((e,[t,a])=>a?(e[t]=a,e):e,{});delete t["time[ge]"],delete t["time[le]"],this.searchDate.from&&(t["time[ge]"]=this.searchDate.from+"T00:00:00"),this.searchDate.to&&(t["time[le]"]=this.searchDate.to+"T23:59:59"),this.paymentsTable.filter=t;try{const t=LNbits.utils.prepareFilterQuery(this.paymentsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/payments/all/paginated?${t}`);this.paymentsTable.pagination.rowsNumber=a.total,this.payments=a.data.map(e=>(e.extra&&e.extra.tag&&(e.tag=e.extra.tag),e.timeFrom=moment.utc(e.created_at).local().fromNow(),e.outgoing=e.amount<0,e.amount=new Intl.NumberFormat(this.g.locale).format(e.amount/1e3)+" sats",e.extra?.wallet_fiat_amount&&(e.amountFiat=this.formatCurrency(e.extra.wallet_fiat_amount,e.extra.wallet_fiat_currency)),e.extra?.internal_memo&&(e.internal_memo=e.extra.internal_memo),e.fee_sats=new Intl.NumberFormat(this.g.locale).format(e.fee/1e3)+" sats",e))}catch(e){console.error(e),LNbits.utils.notifyApiError(e)}finally{this.updateCharts(e)}},async searchPaymentsBy(e,t){e&&(this.searchData[e]=t),await this.fetchPayments()},clearDateSeach(){this.searchDate={from:null,to:null},delete this.paymentsTable.filter["time[ge]"],delete this.paymentsTable.filter["time[le]"],this.fetchPayments()},searchByDate(){"string"==typeof this.searchDate&&(this.searchDate={from:this.searchDate,to:this.searchDate}),this.searchDate.from&&(this.paymentsTable.filter["time[ge]"]=this.searchDate.from+"T00:00:00"),this.searchDate.to&&(this.paymentsTable.filter["time[le]"]=this.searchDate.to+"T23:59:59"),this.fetchPayments()},handleFilterChanged(){const{success:e,pending:t,failed:a,incoming:s,outgoing:i}=this.statusFilters;delete this.searchData["status[ne]"],delete this.searchData["status[eq]"],e&&t&&a||(e&&t?this.searchData["status[ne]"]="failed":e&&a?this.searchData["status[ne]"]="pending":a&&t?this.searchData["status[ne]"]="success":e?this.searchData["status[eq]"]="success":t?this.searchData["status[eq]"]="pending":a&&(this.searchData["status[eq]"]="failed")),delete this.searchData["amount[ge]"],delete this.searchData["amount[le]"],s&&i||(s?this.searchData["amount[ge]"]="0":i&&(this.searchData["amount[le]"]="0")),this.fetchPayments()},showDetailsToggle(e){return this.paymentDetails=e,this.showDetails=!this.showDetails},formatCurrency(e,t){try{return LNbits.utils.formatCurrency(e,t)}catch(t){return console.error(t),`${e} ???`}},shortify:(e,t=10)=>(valueLength=(e||"").length,valueLength<=t?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`),async updateCharts(e){let t=LNbits.utils.prepareFilterQuery(this.paymentsTable,e);try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/count?${t}&count_by=status`);e.sort((e,t)=>e.field-t.field).reverse(),this.searchOptions.status=e.map(e=>e.field),this.paymentsStatusChart.data.datasets[0].data=e.map(e=>e.total),this.paymentsStatusChart.data.labels=[...this.searchOptions.status],this.paymentsStatusChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/wallets?${t}`),a=e.map(e=>e.balance/e.payments_count),s=Math.min(...a),i=Math.max(...a),n=e=>Math.floor(3+22*(e-s)/(i-s)),l=this.randomColors(20),o=e.map((e,t)=>({data:[{x:e.payments_count,y:e.balance,r:n(Math.max(e.balance/e.payments_count,5))}],label:e.wallet_name,wallet_id:e.wallet_id,backgroundColor:l[t%100],hoverOffset:4}));this.paymentsWalletsChart.data.datasets=o,this.paymentsWalletsChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/count?${t}&count_by=tag`);this.searchOptions.tag=e.map(e=>e.field),this.searchOptions.status.sort(),this.paymentsTagsChart.data.datasets[0].data=e.map(e=>e.total),this.paymentsTagsChart.data.labels=e.map(e=>e.field||"core"),this.paymentsTagsChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const t=Object.entries(this.searchData).reduce((e,[t,a])=>a?(e[t]=a,e):e,{}),a={...this.paymentsTable,filter:t},s=LNbits.utils.prepareFilterQuery(a,e);let{data:i}=await LNbits.api.request("GET",`/api/v1/payments/stats/daily?${s}`);const n=this.searchDate.from+"T00:00:00",l=this.searchDate.to+"T23:59:59";this.lnbitsBalance=i.length?i[i.length-1].balance:0,i=i.filter(e=>this.searchDate.from&&this.searchDate.to?e.date>=n&&e.date<=l:this.searchDate.from?e.date>=n:!this.searchDate.to||e.date<=l),this.paymentsDailyChart.data.datasets=[{label:"Balance",data:i.map(e=>e.balance),pointStyle:!1,borderWidth:2,tension:.7,fill:1},{label:"Fees",data:i.map(e=>e.fee),pointStyle:!1,borderWidth:1,tension:.4,fill:1}],this.paymentsDailyChart.data.labels=i.map(e=>e.date.substring(0,10)),this.paymentsDailyChart.update(),this.paymentsBalanceInOutChart.data.datasets=[{label:"Incoming Payments Balance",data:i.map(e=>e.balance_in)},{label:"Outgoing Payments Balance",data:i.map(e=>e.balance_out)}],this.paymentsBalanceInOutChart.data.labels=i.map(e=>e.date.substring(0,10)),this.paymentsBalanceInOutChart.update(),this.paymentsCountInOutChart.data.datasets=[{label:"Incoming Payments Count",data:i.map(e=>e.count_in)},{label:"Outgoing Payments Count",data:i.map(e=>-e.count_out)}],this.paymentsCountInOutChart.data.labels=i.map(e=>e.date.substring(0,10)),this.paymentsCountInOutChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async initCharts(){const e=this.$q.localStorage.getItem("lnbits.payments.chartData")||{};this.chartData={...this.chartData,...e},this.chartsReady?(this.paymentsStatusChart=new Chart(this.$refs.paymentsStatusChart.getContext("2d"),{type:"doughnut",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchPaymentsBy("status",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(0, 205, 86)","rgb(64, 72, 78)","rgb(255, 99, 132)"],hoverOffset:4}]}}),this.paymentsWalletsChart=new Chart(this.$refs.paymentsWalletsChart.getContext("2d"),{type:"bubble",options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{display:!1},title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].datasetIndex;this.searchPaymentsBy("wallet_id",a.data.datasets[e].wallet_id)}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(20),hoverOffset:4}]}}),this.paymentsTagsChart=new Chart(this.$refs.paymentsTagsChart.getContext("2d"),{type:"pie",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!1,title:{display:!1,text:"Tags"}}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchPaymentsBy("tag",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(10),hoverOffset:4}]}}),this.paymentsDailyChart=new Chart(this.$refs.paymentsDailyChart.getContext("2d"),{type:"line",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:"Tags"}}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(10),hoverOffset:4}]}}),this.paymentsBalanceInOutChart=new Chart(this.$refs.paymentsBalanceInOutChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:"Tags"}}},scales:{x:{stacked:!0},y:{stacked:!0}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(50),hoverOffset:4}]}}),this.paymentsCountInOutChart=new Chart(this.$refs.paymentsCountInOutChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:""}}},scales:{x:{stacked:!0},y:{stacked:!0}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(80),hoverOffset:4}]}})):console.warn("Charts are not ready yet. Initialization delayed.")},saveChartsPreferences(){this.$q.localStorage.set("lnbits.payments.chartData",this.chartData)},randomColors(e=1){const t=[];for(let a=1;a<=10;a++)for(let s=1;s<=10;s++)t.push(`rgb(${s*e*33%200}, ${71*(a+s+e)%255}, ${(a+30*e)%255})`);return t}}},window.PageNode={template:"#page-node",config:{globalProperties:{LNbits:LNbits,msg:"hello"}},data(){return{isSuperUser:!1,wallet:{},tab:"dashboard",payments:1e3,info:{},channel_stats:{},channels:{data:[],filter:""},activeBalance:{},ranks:{},peers:{data:[],filter:""},connectPeerDialog:{show:!1,data:{}},setFeeDialog:{show:!1,data:{fee_ppm:0,fee_base_msat:0}},openChannelDialog:{show:!1,data:{}},closeChannelDialog:{show:!1,data:{}},nodeInfoDialog:{show:!1,data:{}},transactionDetailsDialog:{show:!1,data:{}},states:[{label:"Active",value:"active",color:"green"},{label:"Pending",value:"pending",color:"orange"},{label:"Inactive",value:"inactive",color:"grey"},{label:"Closed",value:"closed",color:"red"}],stateFilters:[{label:"Active",value:"active"},{label:"Pending",value:"pending"}],paymentsTable:{data:[],columns:[{name:"pending",label:""},{name:"date",align:"left",label:this.$t("date"),field:"date",sortable:!0},{name:"sat",align:"right",label:this.$t("amount"),field:e=>this.formatMsat(e.amount),sortable:!0},{name:"fee",align:"right",label:this.$t("fee"),field:"fee"},{name:"destination",align:"right",label:"Destination",field:"destination"},{name:"memo",align:"left",label:this.$t("memo"),field:"memo"}],pagination:{rowsPerPage:10,page:1,rowsNumber:10},filter:null},invoiceTable:{data:[],columns:[{name:"pending",label:""},{name:"paid_at",field:"paid_at",align:"left",label:"Paid at",sortable:!0},{name:"expiry",label:this.$t("expiry"),field:"expiry",align:"left",sortable:!0},{name:"amount",label:this.$t("amount"),field:e=>this.formatMsat(e.amount),sortable:!0},{name:"memo",align:"left",label:this.$t("memo"),field:"memo"}],pagination:{rowsPerPage:10,page:1,rowsNumber:10},filter:null}}},created(){this.getInfo(),this.get1MLStats()},watch:{tab(e){"transactions"!==e||this.paymentsTable.data.length?"channels"!==e||this.channels.data.length||(this.getChannels(),this.getPeers()):(this.getPayments(),this.getInvoices())}},computed:{checkChanges(){return!_.isEqual(this.settings,this.formData)},filteredChannels(){return this.stateFilters?this.channels.data.filter(e=>this.stateFilters.find(({value:t})=>t==e.state)):this.channels.data},totalBalance(){return this.filteredChannels.reduce((e,t)=>(e.local_msat+=t.balance.local_msat,e.remote_msat+=t.balance.remote_msat,e.total_msat+=t.balance.total_msat,e),{local_msat:0,remote_msat:0,total_msat:0})}},methods:{formatMsat:e=>LNbits.utils.formatMsat(e),nodeApi(e,t,a){const s=new URLSearchParams(a?.query);return LNbits.api.request(e,`/node/api/v1${t}?${s}`,{},a?.data).catch(e=>{LNbits.utils.notifyApiError(e)})},getChannel(e){return this.nodeApi("GET",`/channels/${e}`).then(e=>{this.setFeeDialog.data.fee_ppm=e.data.fee_ppm,this.setFeeDialog.data.fee_base_msat=e.data.fee_base_msat})},getChannels(){return this.nodeApi("GET","/channels").then(e=>{this.channels.data=e.data})},getInfo(){return this.nodeApi("GET","/info").then(e=>{this.info=e.data,this.channel_stats=e.data.channel_stats}).catch(()=>{this.info={},this.channel_stats={}})},get1MLStats(){return this.nodeApi("GET","/rank").then(e=>{this.ranks=e.data}).catch(()=>{this.ranks={}})},getPayments(e){e&&(this.paymentsTable.pagination=e.pagination);let t=this.paymentsTable.pagination;const a={limit:t.rowsPerPage,offset:(t.page-1)*t.rowsPerPage??0};return this.nodeApi("GET","/payments",{query:a}).then(e=>{this.paymentsTable.data=e.data.data,this.paymentsTable.pagination.rowsNumber=e.data.total})},getInvoices(e){e&&(this.invoiceTable.pagination=e.pagination);let t=this.invoiceTable.pagination;const a={limit:t.rowsPerPage,offset:(t.page-1)*t.rowsPerPage??0};return this.nodeApi("GET","/invoices",{query:a}).then(e=>{this.invoiceTable.data=e.data.data,this.invoiceTable.pagination.rowsNumber=e.data.total})},getPeers(){return this.nodeApi("GET","/peers").then(e=>{this.peers.data=e.data})},connectPeer(){this.nodeApi("POST","/peers",{data:this.connectPeerDialog.data}).then(()=>{this.connectPeerDialog.show=!1,this.getPeers()})},disconnectPeer(e){LNbits.utils.confirmDialog("Do you really wanna disconnect this peer?").onOk(()=>{this.nodeApi("DELETE",`/peers/${e}`).then(e=>{Quasar.Notify.create({message:"Disconnected",icon:null}),this.needsRestart=!0,this.getPeers()})})},setChannelFee(e){this.nodeApi("PUT",`/channels/${e}`,{data:this.setFeeDialog.data}).then(e=>{this.setFeeDialog.show=!1,this.getChannels()}).catch(LNbits.utils.notifyApiError)},openChannel(){this.nodeApi("POST","/channels",{data:this.openChannelDialog.data}).then(e=>{this.openChannelDialog.show=!1,this.getChannels()}).catch(e=>{console.log(e)})},showCloseChannelDialog(e){this.closeChannelDialog.show=!0,this.closeChannelDialog.data={force:!1,short_id:e.short_id,...e.point}},closeChannel(){this.nodeApi("DELETE","/channels",{query:this.closeChannelDialog.data}).then(e=>{this.closeChannelDialog.show=!1,this.getChannels()})},showSetFeeDialog(e){this.setFeeDialog.show=!0,this.setFeeDialog.channel_id=e,this.getChannel(e)},showOpenChannelDialog(e){this.openChannelDialog.show=!0,this.openChannelDialog.data={peer_id:e,funding_amount:0}},showNodeInfoDialog(e){this.nodeInfoDialog.show=!0,this.nodeInfoDialog.data=e},showTransactionDetailsDialog(e){this.transactionDetailsDialog.show=!0,this.transactionDetailsDialog.data=e},shortenNodeId:e=>e?e.substring(0,5)+"..."+e.substring(e.length-5):"..."}},window.PageNodePublic={template:"#page-node-public",data:()=>({enabled:!1,isSuperUser:!1,wallet:{},tab:"dashboard",payments:1e3,info:{},channel_stats:{},channels:[],activeBalance:{},ranks:{},peers:[],connectPeerDialog:{show:!1,data:{}},openChannelDialog:{show:!1,data:{}},closeChannelDialog:{show:!1,data:{}},nodeInfoDialog:{show:!1,data:{}},states:[{label:"Active",value:"active",color:"green"},{label:"Pending",value:"pending",color:"orange"},{label:"Inactive",value:"inactive",color:"grey"},{label:"Closed",value:"closed",color:"red"}]}),created(){this.getInfo(),this.get1MLStats()},methods:{formatMsat:e=>LNbits.utils.formatMsat(e),api:(e,t,a)=>LNbits.api.request(e,"/node/public/api/v1"+t,{},a),getInfo(){this.api("GET","/info",{}).then(e=>{this.info=e.data,this.channel_stats=e.data.channel_stats,this.enabled=!0}).catch(()=>{this.info={},this.channel_stats={}})},get1MLStats(){this.api("GET","/rank",{}).then(e=>{this.ranks=e.data}).catch(()=>{this.ranks={}})}}},window.PageAudit={template:"#page-audit",data:()=>({chartsReady:!1,auditEntries:[],searchData:{user_id:"",ip_address:"",request_type:"",component:"",request_method:"",response_code:"",path:""},searchOptions:{component:[],request_method:[],response_code:[]},auditTable:{columns:[{name:"created_at",align:"center",label:"Date",field:"created_at",sortable:!0},{name:"duration",align:"left",label:"Duration (sec)",field:"duration",sortable:!0},{name:"component",align:"left",label:"Component",field:"component",sortable:!1},{name:"request_method",align:"left",label:"Method",field:"request_method",sortable:!1},{name:"response_code",align:"left",label:"Code",field:"response_code",sortable:!1},{name:"user_id",align:"left",label:"User Id",field:"user_id",sortable:!1},{name:"ip_address",align:"left",label:"IP Address",field:"ip_address",sortable:!1},{name:"path",align:"left",label:"Path",field:"path",sortable:!1}],pagination:{sortBy:"created_at",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},auditDetailsDialog:{data:null,show:!1}}),async created(){},async mounted(){this.chartsReady=!0,await this.$nextTick(),this.initCharts(),await this.fetchAudit()},methods:{async fetchAudit(e){try{const t=LNbits.utils.prepareFilterQuery(this.auditTable,e),{data:a}=await LNbits.api.request("GET",`/audit/api/v1?${t}`);this.auditTable.pagination.rowsNumber=a.total,this.auditEntries=a.data,await this.fetchAuditStats(e)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}finally{this.auditTable.loading=!1}},async fetchAuditStats(e){try{const t=LNbits.utils.prepareFilterQuery(this.auditTable,e),{data:a}=await LNbits.api.request("GET",`/audit/api/v1/stats?${t}`),s=a.request_method.map(e=>e.field);this.searchOptions.request_method=[...new Set(this.searchOptions.request_method.concat(s))],this.requestMethodChart.data.labels=s,this.requestMethodChart.data.datasets[0].data=a.request_method.map(e=>e.total),this.requestMethodChart.update();const i=a.response_code.map(e=>e.field);this.searchOptions.response_code=[...new Set(this.searchOptions.response_code.concat(i))],this.responseCodeChart.data.labels=i,this.responseCodeChart.data.datasets[0].data=a.response_code.map(e=>e.total),this.responseCodeChart.update();const n=a.component.map(e=>e.field);this.searchOptions.component=[...new Set(this.searchOptions.component.concat(n))],this.componentUseChart.data.labels=n,this.componentUseChart.data.datasets[0].data=a.component.map(e=>e.total),this.componentUseChart.update(),this.longDurationChart.data.labels=a.long_duration.map(e=>e.field),this.longDurationChart.data.datasets[0].data=a.long_duration.map(e=>e.total),this.longDurationChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async searchAuditBy(e,t){e&&(this.searchData[e]=t),this.auditTable.filter=Object.entries(this.searchData).reduce((e,[t,a])=>a?(e[t]=a,e):e,{}),await this.fetchAudit()},showDetailsDialog(e){const t=JSON.parse(e?.request_details||"");try{t.body&&(t.body=JSON.parse(t.body))}catch(e){}this.auditDetailsDialog.data=JSON.stringify(t,null,4),this.auditDetailsDialog.show=!0},shortify:e=>(valueLength=(e||"").length,valueLength<=10?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`),async initCharts(){this.chartsReady?(this.responseCodeChart=new Chart(this.$refs.responseCodeChart.getContext("2d"),{type:"doughnut",options:{responsive:!0,plugins:{legend:{position:"bottom"},title:{display:!1,text:"HTTP Response Codes"}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("response_code",a.data.labels[e])}}},data:{datasets:[{label:"",data:[20,10],backgroundColor:["rgb(100, 99, 200)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)"]}],labels:[]}}),this.requestMethodChart=new Chart(this.$refs.requestMethodChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("request_method",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)"],hoverOffset:4}]}}),this.componentUseChart=new Chart(this.$refs.componentUseChart.getContext("2d"),{type:"pie",options:{responsive:!0,plugins:{legend:{position:"xxx"},title:{display:!1,text:"Components"}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("component",a.data.labels[e])}}},data:{datasets:[{data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)","rgb(100, 205, 250)","rgb(120, 205, 250)","rgb(140, 205, 250)","rgb(160, 205, 250)"],hoverOffset:4}]}}),this.longDurationChart=new Chart(this.$refs.longDurationChart.getContext("2d"),{type:"bar",options:{responsive:!0,indexAxis:"y",maintainAspectRatio:!1,plugins:{legend:{title:{display:!1,text:"Long Duration"}}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("path",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)","rgb(100, 205, 250)","rgb(120, 205, 250)","rgb(140, 205, 250)","rgb(160, 205, 250)"],hoverOffset:4}]}})):console.warn("Charts are not ready yet. Initialization delayed.")}}},window.PageWallet={template:"#page-wallet",data:()=>({parse:{show:!1,invoice:null,lnurlpay:null,lnurlauth:null,data:{request:"",amount:0,comment:"",internalMemo:null,unit:"sat"},paymentChecker:null,copy:{show:!1},camera:{show:!1,camera:"auto"}},receive:{show:!1,status:"pending",paymentReq:null,paymentHash:null,amountMsat:null,minMax:[0,21e14],lnurl:null,units:[],unit:"sat",fiatProvider:"",data:{amount:null,memo:"",internalMemo:null,payment_hash:null}},update:{name:null,currency:null},hasNfc:!1,nfcReaderAbortController:null,formattedFiatAmount:0,paymentFilter:{"status[ne]":"failed"},chartConfig:Quasar.LocalStorage.getItem("lnbits.wallets.chartConfig")||{showPaymentInOutChart:!0,showBalanceChart:!0,showBalanceInOutChart:!0}}),computed:{canPay(){return!!this.parse.invoice&&(this.parse.invoice.expired?(Quasar.Notify.create({message:"Invoice has expired",color:"negative"}),!1):this.parse.invoice.sat<=this.g.wallet.sat)},formattedAmount(){return"sat"==this.receive.unit&&this.g.isSatsDenomination?LNbits.utils.formatMsat(this.receive.amountMsat)+" sat":LNbits.utils.formatCurrency(Number(this.receive.data.amount).toFixed(2),this.g.isSatsDenomination?this.receive.unit:this.g.denomination)},formattedSatAmount(){return LNbits.utils.formatMsat(this.receive.amountMsat)+" sat"}},methods:{handleSendLnurl(e){this.parse.data.request=e,this.parse.show=!0,this.lnurlScan()},msatoshiFormat:e=>LNbits.utils.formatSat(e/1e3),showReceiveDialog(){this.receive.show=!0,this.receive.status="pending",this.receive.paymentReq=null,this.receive.paymentHash=null,this.receive.data.amount=null,this.receive.data.memo=null,this.receive.data.internalMemo=null,this.receive.data.payment_hash=null,this.receive.units=["sat",...this.g.allowedCurrencies.length>0?this.g.allowedCurrencies:this.g.currencies],this.receive.unit=this.g.isFiatPriority&&this.g.wallet.currency||"sat",this.receive.minMax=[0,21e14],this.receive.lnurl=null},onReceiveDialogHide(){this.hasNfc&&this.nfcReaderAbortController.abort()},showParseDialog(){this.parse.show=!0,this.parse.invoice=null,this.parse.lnurlpay=null,this.parse.lnurlauth=null,this.parse.copy.show=window.isSecureContext&&void 0!==navigator.clipboard?.readText,this.parse.data.request="",this.parse.data.comment="",this.parse.data.internalMemo=null,this.parse.data.paymentChecker=null,this.parse.camera.show=!1},closeParseDialog(){setTimeout(()=>{clearInterval(this.parse.paymentChecker)},1e4)},handleBalanceUpdate(e){this.g.wallet.sat=this.g.wallet.sat+e},createInvoice(){this.receive.status="loading",this.g.isSatsDenomination||(this.receive.data.amount=100*this.receive.data.amount),LNbits.api.createInvoice(this.g.wallet,this.receive.data.amount,this.receive.data.memo,this.receive.unit,this.receive.lnurlWithdraw,this.receive.fiatProvider,this.receive.data.internalMemo,this.receive.data.payment_hash).then(e=>{if(this.g.updatePayments=!this.g.updatePayments,this.receive.status="success",this.receive.paymentReq=e.data.bolt11,this.receive.fiatPaymentReq=e.data.extra?.fiat_payment_request,this.receive.amountMsat=e.data.amount,this.receive.paymentHash=e.data.payment_hash,this.receive.lnurl||this.readNfcTag(),this.receive.lnurl&&null!==e.data.extra?.lnurl_response){!1===e.data.extra.lnurl_response&&(e.data.extra.lnurl_response="Unable to connect");const t=this.receive.lnurl.callback.split("/")[2];if("string"==typeof e.data.extra.lnurl_response)return void Quasar.Notify.create({timeout:5e3,type:"warning",message:`${t} lnurl-withdraw call failed.`,caption:e.data.extra.lnurl_response});!0===e.data.extra.lnurl_response&&Quasar.Notify.create({timeout:3e3,message:`Invoice sent to ${t}!`,spinner:!0})}}).catch(e=>{LNbits.utils.notifyApiError(e),this.receive.status="pending"})},lnurlScan(){LNbits.api.request("POST","/api/v1/lnurlscan",this.g.wallet.adminkey,{lnurl:this.parse.data.request}).then(e=>{const t=e.data;if("ERROR"!==t.status){if("payRequest"===t.tag)this.parse.lnurlpay=Object.freeze(t),this.parse.data.amount=t.minSendable/1e3;else if("login"===t.tag)this.parse.lnurlauth=Object.freeze(t);else if("withdrawRequest"===t.tag){this.parse.show=!1,this.receive.show=!0,this.receive.lnurlWithdraw=Object.freeze(t),this.receive.status="pending",this.receive.paymentReq=null,this.receive.paymentHash=null,this.receive.data.amount=t.maxWithdrawable/1e3,this.receive.data.memo=t.defaultDescription,this.receive.minMax=[t.minWithdrawable/1e3,t.maxWithdrawable/1e3];const e=t.callback.split("/")[2];this.receive.lnurl={domain:e,callback:t.callback,fixed:t.fixed}}}else Quasar.Notify.create({timeout:5e3,type:"warning",message:"lnurl scan failed.",caption:t.reason})}).catch(e=>{LNbits.utils.notifyApiError(e)})},decodeQR(e){this.parse.data.request=e,this.decodeRequest(),this.parse.camera.show=!1},isLnurl:e=>e.toLowerCase().startsWith("lnurl1")||e.startsWith("lnurlp://")||e.startsWith("lnurlw://")||e.startsWith("lnurlauth://")||e.match(/[\w.+-~_]+@[\w.+-~_]/),decodeRequest(){this.parse.show=!0,this.parse.data.request=this.parse.data.request.trim();const e=this.parse.data.request.toLowerCase();if(e.startsWith("lightning:")?this.parse.data.request=this.parse.data.request.slice(10):e.startsWith("lnurl:")?this.parse.data.request=this.parse.data.request.slice(6):e.includes("lightning=lnurl1")&&(this.parse.data.request=this.parse.data.request.split("lightning=")[1].split("&")[0]),this.isLnurl(this.parse.data.request))return void this.lnurlScan();let t;this.parse.data.request.toLowerCase().includes("lightning")&&(this.parse.data.request=this.parse.data.request.split("lightning=")[1],this.parse.data.request.includes("&")&&(this.parse.data.request=this.parse.data.request.split("&")[0]));try{t=decode(this.parse.data.request)}catch(e){return Quasar.Notify.create({timeout:3e3,type:"warning",message:e+".",caption:"400 BAD REQUEST"}),void(this.parse.show=!1)}let a={msat:t.human_readable_part.amount,sat:t.human_readable_part.amount/1e3,fsat:LNbits.utils.formatSat(t.human_readable_part.amount/1e3),bolt11:this.parse.data.request};_.each(t.data.tags,e=>{if(_.isObject(e)&&_.has(e,"description"))if("payment_hash"===e.description)a.hash=e.value;else if("description"===e.description)a.description=e.value;else if("expiry"===e.description){const s=new Date(1e3*(t.data.time_stamp+e.value)),i=new Date(1e3*t.data.time_stamp);a.expireDate=Quasar.date.formatDate(s,"YYYY-MM-DDTHH:mm:ss.SSSZ"),a.createdDate=Quasar.date.formatDate(i,"YYYY-MM-DDTHH:mm:ss.SSSZ"),a.expireDateFrom=moment.utc(s).local().fromNow(),a.createdDateFrom=moment.utc(i).local().fromNow(),a.expired=!1}}),this.g.wallet.currency&&(a.fiatAmount=LNbits.utils.formatCurrency((a.sat/1e8*this.g.exchangeRate).toFixed(2),this.g.wallet.currency)),this.parse.invoice=Object.freeze(a)},payInvoice(){const e=Quasar.Notify.create({timeout:0,message:this.$t("payment_processing")});LNbits.api.payInvoice(this.g.wallet,this.parse.data.request,this.parse.data.internalMemo).then(t=>{e(),this.g.updatePayments=!this.g.updatePayments,this.parse.show=!1,"success"==t.data.status&&Quasar.Notify.create({type:"positive",message:this.$t("payment_successful")}),"pending"==t.data.status&&Quasar.Notify.create({type:"info",message:this.$t("payment_pending")})}).catch(t=>{e(),LNbits.utils.notifyApiError(t),this.g.updatePayments=!this.g.updatePayments,this.parse.show=!1})},payLnurl(){LNbits.api.request("post","/api/v1/payments/lnurl",this.g.wallet.adminkey,{res:this.parse.lnurlpay,lnurl:this.parse.data.request,unit:this.parse.data.unit,amount:1e3*this.parse.data.amount,comment:this.parse.data.comment,internalMemo:this.parse.data.internalMemo}).then(e=>{if(this.parse.show=!1,e.data.extra.success_action){const t=JSON.parse(e.data.extra.success_action);switch(t.tag){case"url":Quasar.Notify.create({message:`${t.url}`,caption:t.description,html:!0,type:"positive",timeout:0,closeBtn:!0});break;case"message":Quasar.Notify.create({message:t.message,type:"positive",timeout:0,closeBtn:!0});break;case"aes":this.utils.decryptLnurlPayAES(t,e.data.preimage),Quasar.Notify.create({message:value,caption:extra.success_action.description,html:!0,type:"positive",timeout:0,closeBtn:!0})}}}).catch(LNbits.utils.notifyApiError)},authLnurl(){const e=Quasar.Notify.create({timeout:10,message:"Performing authentication..."});LNbits.api.request("post","/api/v1/lnurlauth",wallet.adminkey,this.parse.lnurlauth).then(t=>{e(),Quasar.Notify.create({message:"Authentication successful.",type:"positive",timeout:3500}),this.parse.show=!1}).catch(e=>{e.response.data.reason?Quasar.Notify.create({message:`Authentication failed. ${this.parse.lnurlauth.callback} says:`,caption:e.response.data.reason,type:"warning",timeout:5e3}):LNbits.utils.notifyApiError(e)})},updateWallet(e){LNbits.api.request("PATCH","/api/v1/wallet",this.g.wallet.adminkey,e).then(e=>{this.g.wallet={...this.g.wallet,...e.data};const t=this.g.user.wallets.findIndex(t=>t.id===e.data.id);-1!==t&&(this.g.user.wallets[t]={...this.g.user.wallets[t],...e.data}),Quasar.Notify.create({message:"Wallet updated.",type:"positive",timeout:3500})}).catch(e=>{LNbits.utils.notifyApiError(e)})},pasteToTextArea(){this.$refs.textArea.focus(),navigator.clipboard.readText().then(e=>{this.parse.data.request=e.trim()})},readNfcTag(){try{if("undefined"==typeof NDEFReader)return void console.debug("NFC not supported on this device or browser.");const e=new NDEFReader;this.nfcReaderAbortController=new AbortController,this.nfcReaderAbortController.signal.onabort=e=>{console.debug("All NFC Read operations have been aborted.")},this.hasNfc=!0;const t=Quasar.Notify.create({message:"Tap your NFC tag to pay this invoice with LNURLw."});return e.scan({signal:this.nfcReaderAbortController.signal}).then(()=>{e.onreadingerror=()=>{Quasar.Notify.create({type:"negative",message:"There was an error reading this NFC tag."})},e.onreading=({message:e})=>{const a=new TextDecoder("utf-8"),s=e.records.find(e=>-1!==a.decode(e.data).toUpperCase().indexOf("LNURLW"));if(s){t(),Quasar.Notify.create({type:"positive",message:"NFC tag read successfully."});const e=a.decode(s.data);this.payInvoiceWithNfc(e)}else Quasar.Notify.create({type:"warning",message:"NFC tag does not have LNURLw record."})}})}catch(e){Quasar.Notify.create({type:"negative",message:e?e.toString():"An unexpected error has occurred."})}},payInvoiceWithNfc(e){const t=Quasar.Notify.create({timeout:0,spinner:!0,message:this.$t("processing_payment")});LNbits.api.request("POST",`/api/v1/payments/${this.receive.paymentReq}/pay-with-nfc`,this.g.wallet.adminkey,{lnurl_w:e}).then(e=>{t(),e.data.success?Quasar.Notify.create({type:"positive",message:"Payment successful"}):Quasar.Notify.create({type:"negative",message:e.data.detail||"Payment failed"})}).catch(e=>{t(),LNbits.utils.notifyApiError(e)})}},created(){const e=new URLSearchParams(window.location.search);(e.has("lightning")||e.has("lnurl"))&&(this.parse.data.request=e.get("lightning")||e.get("lnurl"),this.decodeRequest(),this.parse.show=!0);const t=this.g.user.wallets.find(e=>e.id===this.$route.params.id);t?(this.g.wallet=t,this.g.lastActiveWallet=t.id,this.$q.localStorage.setItem("lnbits.lastActiveWallet",t.id),this.$router.replace(`/wallet/${t.id}`)):(this.g.errorCode=404,this.g.errorMessage="Wallet not found.",this.$router.push("/error"))},watch:{"g.updatePaymentsHash"(){this.receive.show=!1},"g.updatePayments"(){this.parse.show=!1,this.g.wallet.currency&&this.$q.localStorage.getItem("lnbits.exchangeRate."+this.g.wallet.currency)&&(this.g.exchangeRate=this.$q.localStorage.getItem("lnbits.exchangeRate."+this.g.wallet.currency),this.g.fiatBalance=this.g.exchangeRate/1e8*this.g.wallet.sat)},"g.wallet"(){this.g.wallet.currency?(this.g.fiatTracking=!0,this.g.fiatBalance=this.g.exchangeRate/1e8*this.g.wallet.sat):(this.g.fiatBalance=0,this.g.fiatTracking=!1)},"g.isFiatPriority"(){this.receive.unit=this.g.isFiatPriority?this.g.wallet.currency:"sat"},"g.fiatBalance"(){this.formattedFiatAmount=LNbits.utils.formatCurrency(this.g.fiatBalance.toFixed(2),this.g.wallet.currency)},"g.exchangeRate"(){this.g.fiatTracking&&this.g.wallet.currency&&(this.g.fiatBalance=this.g.exchangeRate/1e8*this.g.wallet.sat)}}},window.PageWallets={template:"#page-wallets",data:()=>({user:null,tab:"wallets",wallets:[],addWalletDialog:{show:!1},walletsTable:{columns:[{name:"name",align:"left",label:"Name",field:"name",sortable:!0},{name:"currency",align:"center",label:"Currency",field:"currency",sortable:!0},{name:"updated_at",align:"right",label:"Last Updated",field:"updated_at",sortable:!0}],pagination:{sortBy:"updated_at",rowsPerPage:12,page:1,descending:!0,rowsNumber:10},search:"",hideEmpty:!0,loading:!1}}),watch:{"walletsTable.search":{handler(){const e={};this.walletsTable.search&&(e.search=this.walletsTable.search),this.getUserWallets()}}},methods:{async getUserWallets(e){try{this.walletsTable.loading=!0;const t=LNbits.utils.prepareFilterQuery(this.walletsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/wallet/paginated?${t}`,null);this.wallets=a.data,this.walletsTable.pagination.rowsNumber=a.total}catch(e){LNbits.utils.notifyApiError(e)}finally{this.walletsTable.loading=!1}},goToWallet(e){this.$router.push({path:"/wallet",query:{wal:e}})},formattedFiatAmount:(e,t)=>LNbits.utils.formatCurrency(Number(e).toFixed(2),t),formattedSatAmount:e=>LNbits.utils.formatMsat(e)+" sat"},async created(){await this.getUserWallets()}},window.PageUsers={template:"#page-users",data(){return{paymentsWallet:{},cancel:{},users:[],wallets:[],searchData:{user:"",username:"",email:"",pubkey:""},paymentPage:{show:!1},activeWallet:{userId:null,show:!1},activeUser:{data:null,showUserId:!1,show:!1},createWalletDialog:{data:{},show:!1},walletTable:{columns:[{name:"name",align:"left",label:"Name",field:"name"},{name:"id",align:"left",label:"Wallet Id",field:"id"},{name:"currency",align:"left",label:"Currency",field:"currency"},{name:"balance_msat",align:"left",label:"Balance",field:"balance_msat"}],pagination:{sortBy:"name",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},usersTable:{columns:[{name:"activated",align:"left",label:this.$t("activated"),field:"activated",sortable:!1},{name:"wallet_id",align:"left",label:"Wallets",field:"wallet_id",sortable:!1},{name:"id",align:"left",label:"User Id",field:"id",sortable:!1},{name:"username",align:"left",label:"Username",field:"username",sortable:!1},{name:"email",align:"left",label:"Email",field:"email",sortable:!1},{name:"pubkey",align:"left",label:"Public Key",field:"pubkey",sortable:!1},{name:"balance_msat",align:"left",label:"Balance",field:"balance_msat",sortable:!1},{name:"transaction_count",align:"left",label:"Payments",field:"transaction_count",sortable:!1},{name:"last_payment",align:"left",label:"Last Payment",field:"last_payment",sortable:!1}],pagination:{sortBy:"created_at",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},sortFields:[{name:"id",label:"User ID"},{name:"username",label:"Username"},{name:"email",label:"Email"},{name:"pubkey",label:"Public Key"},{name:"created_at",label:"Creation Date"},{name:"updated_at",label:"Last Updated"}],search:null,hideEmpty:!0,loading:!1}}},watch:{"usersTable.hideEmpty":function(e,t){this.usersTable.filter=e?{"transaction_count[gt]":0}:{},this.fetchUsers()}},created(){this.fetchUsers()},methods:{formatSat:e=>LNbits.utils.formatSat(Math.floor(e/1e3)),backToUsersPage(){this.activeUser.show=!1,this.paymentPage.show=!1,this.activeWallet.show=!1,this.fetchUsers()},handleBalanceUpdate(){this.fetchWallets(this.activeWallet.userId)},resetPassword(e){return LNbits.api.request("PUT",`/users/api/v1/user/${e}/reset_password`).then(e=>{LNbits.utils.confirmDialog(this.$t("reset_key_generated")+" "+this.$t("reset_key_copy")).onOk(()=>{const t=window.location.origin+"?reset_key="+e.data;this.utils.copyText(t)})}).catch(LNbits.utils.notifyApiError)},sortByColumn(e){this.usersTable.pagination.sortBy===e?this.usersTable.pagination.descending=!this.usersTable.pagination.descending:(this.usersTable.pagination.sortBy=e,this.usersTable.pagination.descending=!1),this.fetchUsers()},createUser(){LNbits.api.request("POST","/users/api/v1/user",null,this.activeUser.data).then(e=>{Quasar.Notify.create({type:"positive",message:"User created!",icon:null}),this.activeUser.setPassword=!0,this.activeUser.data=e.data,this.fetchUsers()}).catch(LNbits.utils.notifyApiError)},updateUser(){LNbits.api.request("PUT",`/users/api/v1/user/${this.activeUser.data.id}`,null,this.activeUser.data).then(()=>{Quasar.Notify.create({type:"positive",message:"User updated!",icon:null}),this.activeUser.data=null,this.activeUser.show=!1,this.fetchUsers()}).catch(LNbits.utils.notifyApiError)},createWallet(){const e=this.activeWallet.userId;e?LNbits.api.request("POST",`/users/api/v1/user/${e}/wallet`,null,this.createWalletDialog.data).then(()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"Wallet created!"})}).catch(LNbits.utils.notifyApiError):Quasar.Notify.create({type:"warning",message:"No user selected!",icon:null})},deleteUser(e){LNbits.utils.confirmDialog("Are you sure you want to delete this user?").onOk(()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}`).then(()=>{this.fetchUsers(),Quasar.Notify.create({type:"positive",message:"User deleted!",icon:null}),this.activeUser.data=null,this.activeUser.show=!1}).catch(LNbits.utils.notifyApiError)})},undeleteUserWallet(e,t){LNbits.api.request("PUT",`/users/api/v1/user/${e}/wallet/${t}/undelete`).then(()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"Undeleted user wallet!",icon:null})}).catch(LNbits.utils.notifyApiError)},deleteUserWallet(e,t,a){const s=a?"Wallet is already deleted, are you sure you want to permanently delete this user wallet?":"Are you sure you want to delete this user wallet?";LNbits.utils.confirmDialog(s).onOk(()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}/wallet/${t}`).then(()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"User wallet deleted!",icon:null})}).catch(LNbits.utils.notifyApiError)})},deleteAllUserWallets(e){LNbits.utils.confirmDialog(this.$t("confirm_delete_all_wallets")).onOk(()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}/wallets`).then(t=>{Quasar.Notify.create({type:"positive",message:t.data.message,icon:null}),this.fetchWallets(e)}).catch(LNbits.utils.notifyApiError)})},copyWalletLink(e){const t=`${window.location.origin}/wallet?usr=${this.activeWallet.userId}&wal=${e}`;this.utils.copyText(t)},fetchUsers(e){this.relaxFilterForFields(["username","email"]);const t=LNbits.utils.prepareFilterQuery(this.usersTable,e);LNbits.api.request("GET",`/users/api/v1/user?${t}`).then(e=>{this.usersTable.loading=!1,this.usersTable.pagination.rowsNumber=e.data.total,this.users=e.data.data}).catch(LNbits.utils.notifyApiError)},fetchWallets(e){return LNbits.api.request("GET",`/users/api/v1/user/${e}/wallet`).then(t=>{this.wallets=t.data,this.activeWallet.userId=e,this.activeWallet.show=!0}).catch(LNbits.utils.notifyApiError)},relaxFilterForFields(e=[]){e.forEach(e=>{const t=this.usersTable?.filter?.[e];t&&this.usersTable.filter[e]&&(this.usersTable.filter[`${e}[like]`]=t,delete this.usersTable.filter[e])})},updateWallet(e){LNbits.api.request("PATCH","/api/v1/wallet",e.adminkey,{name:e.name}).then(()=>{e.editable=!1,Quasar.Notify.create({message:"Wallet name updated.",type:"positive",timeout:3500})}).catch(e=>{LNbits.utils.notifyApiError(e)})},toggleAdmin(e){LNbits.api.request("PUT",`/users/api/v1/user/${e}/admin`).then(()=>{this.fetchUsers(),Quasar.Notify.create({type:"positive",message:"Toggled admin!",icon:null})}).catch(LNbits.utils.notifyApiError)},toggleUserActivated(e){LNbits.api.request("PUT",`/users/api/v1/user/${e}/activate`).then(e=>{this.fetchUsers(),Quasar.Notify.create({type:"positive",message:e.data.message,icon:null})}).catch(LNbits.utils.notifyApiError)},async showAccountPage(e){if(this.activeUser.showPassword=!1,this.activeUser.showUserId=!1,this.activeUser.setPassword=!1,!e)return this.activeUser.data={extra:{}},void(this.activeUser.show=!0);try{const{data:t}=await LNbits.api.request("GET",`/users/api/v1/user/${e}`);this.activeUser.data=t,this.activeUser.show=!0}catch(e){console.warn(e),Quasar.Notify.create({type:"warning",message:"Failed to get user!"}),this.activeUser.show=!1}},async impersonateUser(e){try{await LNbits.api.impersonateUser(e),LNbits.utils.backupLocalStorage("impersonation",!0),this.$q.localStorage.setItem("lnbits.disclaimerShown",!0),window.location="/wallet"}catch(e){console.warn(e),Quasar.Notify.create({type:"warning",message:"Failed to impersonate user!"})}},async showWalletPayments(e){this.activeUser.show=!1,await this.fetchWallets(this.users[0].id),await this.showPayments(e)},showPayments(e){this.paymentsWallet=this.wallets.find(t=>t.id===e),this.paymentPage.show=!0},searchUserBy(e){const t=this.searchData[e];this.usersTable.filter={},t&&(this.usersTable.filter[e]=t),this.fetchUsers()},shortify:e=>(valueLength=(e||"").length,valueLength<=10?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`)}},window.PageAccount={template:"#page-account",data(){return{untouchedUser:null,hasUsername:!1,showUserId:!1,themeOptions:[{name:"bitcoin",color:"deep-orange"},{name:"classic",color:"purple"},{name:"mint",color:"green"},{name:"autumn",color:"brown"},{name:"monochrome",color:"grey"},{name:"salvador",color:"blue-10"},{name:"freedom",color:"pink-13"},{name:"cyber",color:"light-green-9"},{name:"flamingo",color:"pink-3"}],defaultSiteCustomisation:{locale:"en"},reactionOptions:["None","confettiBothSides","confettiFireworks","confettiStars","confettiTop"],borderOptions:["retro-border","hard-border","neon-border","no-border"],tab:"user",credentialsData:{show:!1,oldPassword:null,newPassword:null,newPasswordRepeat:null,username:null,pubkey:null},apiAcl:{showNewAclDialog:!1,showPasswordDialog:!1,showNewTokenDialog:!1,data:[],passwordGuardedFunction:null,newAclName:"",newTokenName:"",password:"",apiToken:null,selectedTokenId:null,columns:[{name:"Name",align:"left",label:this.$t("Name"),field:"Name",sortable:!1},{name:"path",align:"left",label:this.$t("path"),field:"path",sortable:!1},{name:"read",align:"left",label:this.$t("read"),field:"read",sortable:!1},{name:"write",align:"left",label:this.$t("write"),field:"write",sortable:!1}],pagination:{rowsPerPage:100,page:1}},selectedApiAcl:{id:null,name:null,endpoints:[],token_id_list:[],allRead:!1,allWrite:!1},assets:[],assetsTable:{loading:!1,columns:[{name:"name",align:"left",label:this.$t("Name"),field:"name",sortable:!0},{name:"created_at",align:"left",label:this.$t("created_at"),field:"created_at",sortable:!0}],pagination:{rowsPerPage:6,page:1}},assetsUploadToPublic:!1,notifications:{nostr:{identifier:""}},labels:[],labelsDialog:{show:!1,data:{name:"",description:"",color:"#000000"}},labelsTable:{loading:!1,columns:[{name:"actions",align:"left"},{name:"name",align:"left",label:this.$t("Name"),field:"name",sortable:!0},{name:"description",align:"left",label:this.$t("description"),field:"description"},{name:"color",align:"left",label:this.$t("color"),field:"color"}],pagination:{rowsPerPage:6,page:1}}}},watch:{tab(e){this.$router.push(`/account#${e}`)},$route(e){e.hash.length>1&&(this.tab=e.hash.replace("#",""))},"assetsTable.search":{handler(){const e={};this.assetsTable.search&&(e.search=this.assetsTable.search),this.getUserAssets()}}},computed:{isUserTouched(){return!_.isEqual(this.g.user,this.untouchedUser)}},methods:{changeLanguage(e){window.i18n.global.locale=e,this.$q.localStorage.set("lnbits.lang",e)},async updateAccount(){try{const{data:e}=await LNbits.api.request("PATCH","/api/v1/auth",null,{user_id:this.g.user.id,username:this.g.user.username,email:this.g.user.email,extra:this.g.user.extra});this.untouchedUser=JSON.parse(JSON.stringify(this.g.user)),this.hasUsername=!!e.username,Quasar.Notify.create({type:"positive",message:"Account updated."})}catch(e){LNbits.utils.notifyApiError(e)}},disableUpdatePassword(){return!this.credentialsData.newPassword||!this.credentialsData.newPasswordRepeat||this.credentialsData.newPassword!==this.credentialsData.newPasswordRepeat},async updatePassword(){if(this.credentialsData.username)try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/password",null,{user_id:this.g.user.id,username:this.credentialsData.username,password_old:this.credentialsData.oldPassword,password:this.credentialsData.newPassword,password_repeat:this.credentialsData.newPasswordRepeat});this.untouchedUser=JSON.parse(JSON.stringify(e)),this.hasUsername=!!e.username,this.credentialsData.show=!1,Quasar.Notify.create({type:"positive",message:"Password updated."})}catch(e){LNbits.utils.notifyApiError(e)}else Quasar.Notify.create({type:"warning",message:"Please set a username."})},async updatePubkey(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/pubkey",null,{user_id:this.g.user.id,pubkey:this.credentialsData.pubkey});this.untouchedUser=JSON.parse(JSON.stringify(e)),this.hasUsername=!!e.username,this.credentialsData.show=!1,this.$q.notify({type:"positive",message:"Public key updated."})}catch(e){LNbits.utils.notifyApiError(e)}},showUpdateCredentials(){this.credentialsData={show:!0,oldPassword:null,username:this.g.user.username,pubkey:this.g.user.pubkey,newPassword:null,newPasswordRepeat:null}},newApiAclDialog(){this.apiAcl.newAclName=null,this.apiAcl.showNewAclDialog=!0},newTokenAclDialog(){this.apiAcl.newTokenName=null,this.apiAcl.newTokenExpiry=null,this.apiAcl.showNewTokenDialog=!0},handleApiACLSelected(e){this.selectedApiAcl={id:null,name:null,endpoints:[],token_id_list:[]},this.apiAcl.selectedTokenId=null,e&&setTimeout(()=>{const t=this.apiAcl.data.find(t=>t.id===e);this.selectedApiAcl&&(this.selectedApiAcl={...t},this.selectedApiAcl.allRead=this.selectedApiAcl.endpoints.every(e=>e.read),this.selectedApiAcl.allWrite=this.selectedApiAcl.endpoints.every(e=>e.write))})},handleAllEndpointsReadAccess(){this.selectedApiAcl.endpoints.forEach(e=>e.read=this.selectedApiAcl.allRead)},handleAllEndpointsWriteAccess(){this.selectedApiAcl.endpoints.forEach(e=>e.write=this.selectedApiAcl.allWrite)},async getApiACLs(){try{const{data:e}=await LNbits.api.request("GET","/api/v1/auth/acl",null);this.apiAcl.data=e.access_control_list}catch(e){LNbits.utils.notifyApiError(e)}},askPasswordAndRunFunction(e){this.apiAcl.passwordGuardedFunction=e,this.apiAcl.showPasswordDialog=!0},runPasswordGuardedFunction(){this.apiAcl.showPasswordDialog=!1;const e=this.apiAcl.passwordGuardedFunction;e&&this[e]()},async addApiACL(){if(this.apiAcl.newAclName){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/acl",null,{id:this.apiAcl.newAclName,name:this.apiAcl.newAclName,password:this.apiAcl.password});this.apiAcl.data=e.access_control_list;const t=this.apiAcl.data.find(e=>e.name===this.apiAcl.newAclName);this.handleApiACLSelected(t.id),this.apiAcl.showNewAclDialog=!1,this.$q.notify({type:"positive",message:"Access Control List created."})}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.name="",this.apiAcl.password=""}this.apiAcl.showNewAclDialog=!1}else this.$q.notify({type:"warning",message:"Name is required."})},async updateApiACLs(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/acl",null,{id:this.g.user.id,password:this.apiAcl.password,...this.selectedApiAcl});this.apiAcl.data=e.access_control_list}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async deleteApiACL(){if(this.selectedApiAcl.id){try{await LNbits.api.request("DELETE","/api/v1/auth/acl",null,{id:this.selectedApiAcl.id,password:this.apiAcl.password}),this.$q.notify({type:"positive",message:"Access Control List deleted."})}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}this.apiAcl.data=this.apiAcl.data.filter(e=>e.id!==this.selectedApiAcl.id),this.handleApiACLSelected(this.apiAcl.data[0]?.id)}},async generateApiToken(){if(!this.selectedApiAcl.id)return;const e=new Date(this.apiAcl.newTokenExpiry)-new Date;try{const{data:t}=await LNbits.api.request("POST","/api/v1/auth/acl/token",null,{acl_id:this.selectedApiAcl.id,token_name:this.apiAcl.newTokenName,password:this.apiAcl.password,expiration_time_minutes:Math.trunc(e/6e4)});this.apiAcl.apiToken=t.api_token,this.apiAcl.selectedTokenId=t.id,Quasar.Notify.create({type:"positive",message:"Token Generated."}),await this.getApiACLs(),this.handleApiACLSelected(this.selectedApiAcl.id),this.apiAcl.showNewTokenDialog=!1}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async deleteToken(){if(this.apiAcl.selectedTokenId)try{await LNbits.api.request("DELETE","/api/v1/auth/acl/token",null,{id:this.apiAcl.selectedTokenId,acl_id:this.selectedApiAcl.id,password:this.apiAcl.password}),this.$q.notify({type:"positive",message:"Token deleted."}),this.selectedApiAcl.token_id_list=this.selectedApiAcl.token_id_list.filter(e=>e.id!==this.apiAcl.selectedTokenId),this.apiAcl.selectedTokenId=null}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async getUserAssets(e){try{this.assetsTable.loading=!0;const t=LNbits.utils.prepareFilterQuery(this.assetsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/assets/paginated?${t}`,null);this.assets=a.data,this.assetsTable.pagination.rowsNumber=a.total}catch(e){LNbits.utils.notifyApiError(e)}finally{this.assetsTable.loading=!1}},onImageInput(e){const t=e.target.files[0];t&&this.uploadAsset(t),e.target.value=null},onBackgroundImageInput(e){const t=e.target.files[0];t&&this.uploadBackgroundImage(t),e.target.value=null},async uploadAsset(e,{isPublic:t=this.assetsUploadToPublic,notifySuccess:a=!0}={}){const s=new FormData;s.append("file",e);try{const{data:e}=await LNbits.api.request("POST",`/api/v1/assets?public_asset=${t}`,null,s,{headers:{"Content-Type":"multipart/form-data"}});return a&&this.$q.notify({type:"positive",message:"Upload successful!",icon:null}),await this.getUserAssets(),e}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async uploadBackgroundImage(e){const t=await this.uploadAsset(e,{isPublic:!1,notifySuccess:!1});if(!t)return;const a=`${window.location.origin}/api/v1/assets/${t.id}/thumbnail`;await this.siteCustomisationChanged({bgimageChoice:a})},async deleteAsset(e){LNbits.utils.confirmDialog("Are you sure you want to delete this asset?").onOk(async()=>{try{await LNbits.api.request("DELETE",`/api/v1/assets/${e.id}`,null),this.$q.notify({type:"positive",message:"Asset deleted."}),await this.getUserAssets()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}})},async toggleAssetPublicAccess(e){try{await LNbits.api.request("PUT",`/api/v1/assets/${e.id}`,null,{is_public:!e.is_public}),this.$q.notify({type:"positive",message:"Update successful!",icon:null}),await this.getUserAssets()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},copyAssetLinkToClipboard(e){const t=`${window.location.origin}/api/v1/assets/${e.id}/data`;this.utils.copyText(t)},addUserLabel(){if(!this.labelsDialog.data.name)return void this.$q.notify({type:"warning",message:"Name is required."});if(!this.labelsDialog.data.color)return void this.$q.notify({type:"warning",message:"Color is required."});this.g.user.extra.labels=this.g.user.extra.labels||[];if(!this.g.user.extra.labels.find(e=>e.name===this.labelsDialog.data.name))return this.g.user.extra.labels.unshift({...this.labelsDialog.data}),this.labelsDialog.show=!1,!0;this.$q.notify({type:"warning",message:"A label with this name already exists."})},openAddLabelDialog(){this.labelsDialog.data={name:"",description:"",color:"#000000"},this.labelsDialog.show=!0},openEditLabelDialog(e){this.labelsDialog.data={name:e.name,description:e.description,color:e.color},this.labelsDialog.show=!0},updateUserLabel(){const e=this.labelsDialog.data,t=JSON.parse(JSON.stringify(this.g.user.extra.labels));this.g.user.extra.labels=this.g.user.extra.labels.filter(t=>t.name!==e.name);this.addUserLabel()||(this.g.user.extra.labels=t),this.labelsDialog.show=!1},deleteUserLabel(e){LNbits.utils.confirmDialog("Are you sure you want to delete this label?").onOk(()=>{this.g.user.extra.labels=this.g.user.extra.labels.filter(t=>t.name!==e.name)})},async siteCustomisationChanged(e={}){try{Object.entries(e||{}).forEach(([e,t])=>{e in this.g&&(this.g[e]=t)}),await LNbits.api.updateUiCustomization(e),this.$q.notify({type:"positive",message:"UI Customization updated."})}catch(e){LNbits.utils.notifyApiError(e)}},resetThemeDefaults(){const e={themeChoice:this.g.settings.defaultTheme,borderChoice:this.g.settings.defaultBorder,gradientChoice:this.g.settings.defaultGradient,bgimageChoice:this.g.settings.defaultBgimage||"",reactionChoice:this.g.settings.defaultReaction,darkChoice:this.g.settings.defaultDark,cardRoundedChoice:this.g.settings.defaultCardRounded,cardGradientChoice:this.g.settings.defaultCardGradient,cardShadowChoice:this.g.settings.defaultCardShadow};this.siteCustomisationChanged(e)}},async created(){this.untouchedUser=JSON.parse(JSON.stringify(this.g.user)),this.hasUsername=!!this.g.user.username,this.$route.hash.length>1&&(this.tab=this.$route.hash.replace("#","")),await this.getApiACLs(),await this.getUserAssets(),this.themeOptions=this.themeOptions.filter(e=>this.g.settings.themeOptions.includes(e.name))}},window.PageAdmin={template:"#page-admin",data:()=>({tab:"funding",settings:{},formData:{lnbits_exchange_rate_providers:[],lnbits_audit_exclude_paths:[],lnbits_audit_include_paths:[],lnbits_audit_http_response_codes:[]},isSuperUser:!1,needsRestart:!1}),watch:{tab(e){this.$router.push(`/admin#${e}`)},$route(e){e.hash.length>1&&(this.tab=e.hash.replace("#",""))}},async created(){this.$route.hash.length>1&&(this.tab=this.$route.hash.replace("#","")),await this.getSettings()},computed:{checkChanges(){return!_.isEqual(this.settings,this.formData)}},methods:{getDefaultSetting(e){LNbits.api.getDefaultSetting(e).then(t=>{this.formData[e]=t.data.default_value})},restartServer(){LNbits.api.request("GET","/admin/api/v1/restart/").then(e=>{this.$q.notify({type:"positive",message:"Success! Restarted Server",icon:null}),this.needsRestart=!1}).catch(LNbits.utils.notifyApiError)},async getSettings(){await LNbits.api.request("GET","/admin/api/v1/settings",this.g.user.wallets[0].adminkey).then(e=>{this.isSuperUser=e.data.is_super_user||!1,this.settings=e.data,this.formData={...this.settings}}).catch(LNbits.utils.notifyApiError)},updateSettings(){const e=_.omit(this.formData,["is_super_user","lnbits_allowed_funding_sources","touch"]);LNbits.api.request("PUT","/admin/api/v1/settings",this.g.user.wallets[0].adminkey,e).then(e=>{this.needsRestart=this.settings.lnbits_backend_wallet_class!==this.formData.lnbits_backend_wallet_class,this.settings=this.formData,this.formData=_.clone(this.settings),Quasar.Notify.create({type:"positive",message:"Success! Settings changed! "+(this.needsRestart?"Restart required!":""),icon:null})}).catch(LNbits.utils.notifyApiError)},deleteSettings(){LNbits.utils.confirmDialog("Are you sure you want to restore settings to default?").onOk(()=>{LNbits.api.request("DELETE","/admin/api/v1/settings").then(e=>{Quasar.Notify.create({type:"positive",message:"Success! Restored settings to defaults. Restarting...",icon:null}),this.$q.localStorage.clear()}).catch(LNbits.utils.notifyApiError)})},downloadBackup(){window.open("/admin/api/v1/backup","_blank")}}},window.app.component("lnbits-admin-funding",{props:["is-super-user","form-data","settings"],template:"#lnbits-admin-funding",data:()=>({auditData:[]}),created(){this.getAudit()},methods:{getAudit(){LNbits.api.request("GET","/admin/api/v1/audit",this.g.user.wallets[0].adminkey).then(e=>{this.auditData=e.data}).catch(LNbits.utils.notifyApiError)}}}),window.app.component("lnbits-admin-funding-sources",{template:"#lnbits-admin-funding-sources",props:["form-data","allowed-funding-sources"],methods:{getFundingSourceLabel(e){const t=this.rawFundingSources.find(t=>t[0]===e);return t?t[1]:e},showQRValue(e){this.qrValue=e,this.showQRDialog=!0}},computed:{fundingSources(){let e=[];for(const[t,a,s]of this.rawFundingSources){const a={};if(null!==s)for(let[e,t]of Object.entries(s))a[e]="string"==typeof t?{label:t,value:null}:t||{};e.push([t,a])}return new Map(e)},sortedAllowedFundingSources(){return this.allowedFundingSources.sort()}},data:()=>({hideInput:!0,showQRDialog:!1,qrValue:"",rawFundingSources:[["VoidWallet","Void Wallet",null],["FakeWallet","Fake Wallet",{fake_wallet_secret:"Secret",lnbits_denomination:'"sats" or 3 Letter Custom Denomination'}],["CLNRestWallet","Core Lightning Rest (plugin)",{clnrest_url:"Endpoint",clnrest_ca:"ca.pem",clnrest_cert:"server.pem",clnrest_readonly_rune:"Rune used for readonly requests",clnrest_invoice_rune:"Rune used for creating invoices",clnrest_pay_rune:"Rune used for paying invoices using pay",clnrest_renepay_rune:"Rune used for paying invoices using renepay",clnrest_last_pay_index:"Ignores any invoices paid prior to or including this index. 0 is equivalent to not specifying and negative value is invalid.",clnrest_nodeid:"Node id"}],["CoreLightningWallet","Core Lightning",{corelightning_rpc:"Endpoint",corelightning_pay_command:"Custom Pay Command"}],["CoreLightningRestWallet","Core Lightning Rest (legacy)",{corelightning_rest_url:"Endpoint",corelightning_rest_cert:"Certificate",corelightning_rest_macaroon:"Macaroon"}],["LndRestWallet","Lightning Network Daemon (LND Rest)",{lnd_rest_endpoint:"Endpoint",lnd_rest_cert:"Certificate",lnd_rest_macaroon:"Macaroon",lnd_rest_macaroon_encrypted:"Encrypted Macaroon",lnd_rest_route_hints:{advanced:!0,label:"Enable Route Hints"},lnd_rest_allow_self_payment:{advanced:!0,label:"Allow Self Payment"}}],["LndWallet","Lightning Network Daemon (LND)",{lnd_grpc_endpoint:"Endpoint",lnd_grpc_cert:"Certificate",lnd_grpc_port:"Port",lnd_grpc_macaroon:"GRPC Macaroon",lnd_grpc_invoice_macaroon:"GRPC Invoice Macaroon",lnd_grpc_admin_macaroon:"GRPC Admin Macaroon",lnd_grpc_macaroon_encrypted:"Encrypted Macaroon"}],["LnTipsWallet","LN.Tips",{lntips_api_endpoint:"Endpoint",lntips_api_key:"API Key"}],["LNPayWallet","LN Pay",{lnpay_api_endpoint:"Endpoint",lnpay_api_key:"API Key",lnpay_wallet_key:"Wallet Key"}],["EclairWallet","Eclair (ACINQ)",{eclair_url:"URL",eclair_pass:"Password"}],["LNbitsWallet","LNbits",{lnbits_endpoint:"Endpoint",lnbits_key:"Admin Key"}],["BlinkWallet","Blink",{blink_api_endpoint:"Endpoint",blink_ws_endpoint:"WebSocket",blink_token:"Key"}],["AlbyWallet","Alby",{alby_api_endpoint:"Endpoint",alby_access_token:"Key"}],["BoltzWallet","Boltz",{boltz_client_endpoint:{label:"Boltz client endpoint",value:"127.0.0.1:9002"},boltz_client_macaroon:{label:"Admin Macaroon path or hex",value:"/home/ubuntu/.boltz/macaroons/admin.macaroon"},boltz_client_cert:{label:"Certificate path or hex",value:"/home/ubuntu/.boltz/tls.cert"},boltz_mnemonic:{label:"Liquid seed phrase",hint:"Boltz will fetch once connected, but you can change later (can be opened in a liquid wallet) ",copy:!0,qrcode:!0},boltz_client_password:{label:"Wallet Password (optional)",advanced:!0}}],["ZBDWallet","ZBD",{zbd_api_endpoint:"Endpoint",zbd_api_key:"Key"}],["PhoenixdWallet","Phoenixd",{phoenixd_api_endpoint:"Endpoint",phoenixd_api_password:"Key",phoenixd_data_dir:{label:"Data Directory",hint:"Directory where phoenixd stores its data, including the seed phrase."},phoenixd_mnemonic:{label:"Phoenixd Seed Phrase",hint:"Only available if phoenixd data-dir is specified",readonly:!0,copy:!0,qrcode:!0}}],["OpenNodeWallet","OpenNode",{opennode_api_endpoint:"Endpoint",opennode_key:"Key"}],["ClicheWallet","Cliche (NBD)",{cliche_endpoint:"Endpoint"}],["SparkWallet","Spark",{spark_url:"Endpoint",spark_token:"Token"}],["SparkL2Wallet","Spark (L2)",{spark_l2_external_endpoint:{label:"External Sidecar Endpoint",hint:"Make sure to also specify the API key if your sidecar requires authentication.",value:""},spark_l2_mnemonic:{label:"External Sidecar Mnemonic",hint:"Mnemonic for the Spark wallet on the external sidecar. Required if the side car does not have its own mnemonic.",value:""},spark_l2_external_api_key:{label:"External Sidecar API Key",hint:"API key for authenticating with the external sidecar if it requires authentication.",value:""},spark_l2_network:{label:"Network",value:"MAINNET",hint:"The network to use for the Spark wallet.",advanced:!0},spark_l2_pay_wait_ms:{label:"Payment Wait Time (ms)",hint:"The time to wait for a payment to be processed before considering it failed.",advanced:!0},spark_l2_pay_poll_ms:{label:"Payment Poll Time (ms)",hint:"The time to wait between polling for payment status updates.",advanced:!0},spark_l2_stream_keepalive_ms:{label:"Stream Keepalive Time (ms)",hint:"The time to wait between sending keepalive messages to the Spark sidecar to keep the connection open.",advanced:!0}}],["NWCWallet","Nostr Wallet Connect",{nwc_pairing_url:"Pairing URL"}],["BreezSdkWallet","Breez SDK",{breez_api_key:"Breez API Key",breez_greenlight_seed:"Greenlight Seed",breez_greenlight_device_key:"Greenlight Device Key",breez_greenlight_device_cert:"Greenlight Device Cert",breez_greenlight_invite_code:"Greenlight Invite Code"}],["StrikeWallet","Strike (alpha)",{strike_api_endpoint:"API Endpoint",strike_api_key:"API Key"}],["BreezLiquidSdkWallet","Breez Liquid SDK",{breez_liquid_api_key:"Breez API Key (can be empty)",breez_liquid_seed:"Liquid seed phrase",breez_liquid_fee_offset_sat:"Offset amount in sats to increase fee limit"}]]})}),window.app.component("lnbits-admin-fiat-providers",{props:["form-data"],template:"#lnbits-admin-fiat-providers",data:()=>({formAddStripeUser:"",formAddPaypalUser:"",formAddSquareUser:"",formAddRevolutUser:"",creatingRevolutWebhook:!1,hideInputToggle:!0}),computed:{stripeWebhookUrl(){return this.formData?.stripe_payment_webhook_url||this.calculateWebhookUrl("stripe")},paypalWebhookUrl(){return this.formData?.paypal_payment_webhook_url||this.calculateWebhookUrl("paypal")},revolutWebhookUrl(){return this.formData?.revolut_payment_webhook_url||this.calculateWebhookUrl("revolut")}},watch:{formData:{handler(){this.syncWebhookUrls()},immediate:!0}},methods:{basePathFromLocation(){if("undefined"==typeof window)return"";const e=window.location.pathname.replace(/\/+$/,""),t=e.lastIndexOf("/admin");return(t>=0?e.slice(0,t):e||"")||""},calculateWebhookUrl(e){if("undefined"==typeof window)return"";const t=`${this.basePathFromLocation()}/api/v1/callback/${e}`.replace(/\/+/g,"/"),a=t.startsWith("/")?t:`/${t}`;return`${window.location.origin}${a}`},syncWebhookUrls(){this.maybeSetWebhookUrl("stripe_payment_webhook_url","stripe"),this.maybeSetWebhookUrl("paypal_payment_webhook_url","paypal"),this.maybeSetWebhookUrl("square_payment_webhook_url","square"),this.maybeSetWebhookUrl("revolut_payment_webhook_url","revolut")},maybeSetWebhookUrl(e,t){if(!this.formData)return;const a=this.calculateWebhookUrl(t),s=this.formData[e];(!s||s.includes("your-lnbits-domain-here.com"))&&a&&(this.formData[e]=a)},copyWebhookUrl(e){e&&this.copyText(e)},isClearnetWebhookUrl(e){let t;try{t=new URL(e)}catch(e){return!1}const a=t.hostname.toLowerCase();return!!["http:","https:"].includes(t.protocol)&&(!("localhost"===a||a.endsWith(".localhost")||a.endsWith(".local")||a.endsWith(".onion"))&&!(/^127\./.test(a)||/^10\./.test(a)||/^192\.168\./.test(a)||/^169\.254\./.test(a)||/^172\.(1[6-9]|2\d|3[0-1])\./.test(a)||"0.0.0.0"===a||"::1"===a))},notifyRevolutWebhookWarning(e){Quasar.Notify.create({type:"warning",message:e,icon:null,closeBtn:!0})},addStripeAllowedUser(){const e=this.formAddStripeUser||"";e.length&&!this.formData.stripe_limits.allowed_users.includes(e)&&(this.formData.stripe_limits.allowed_users=[...this.formData.stripe_limits.allowed_users,e],this.formAddStripeUser="")},removeStripeAllowedUser(e){this.formData.stripe_limits.allowed_users=this.formData.stripe_limits.allowed_users.filter(t=>t!==e)},addPaypalAllowedUser(){const e=this.formAddPaypalUser||"";e.length&&!this.formData.paypal_limits.allowed_users.includes(e)&&(this.formData.paypal_limits.allowed_users=[...this.formData.paypal_limits.allowed_users,e],this.formAddPaypalUser="")},removePaypalAllowedUser(e){this.formData.paypal_limits.allowed_users=this.formData.paypal_limits.allowed_users.filter(t=>t!==e)},addSquareAllowedUser(){const e=this.formAddSquareUser||"";e.length&&!this.formData.square_limits.allowed_users.includes(e)&&(this.formData.square_limits.allowed_users=[...this.formData.square_limits.allowed_users,e],this.formAddSquareUser="")},removeSquareAllowedUser(e){this.formData.square_limits.allowed_users=this.formData.square_limits.allowed_users.filter(t=>t!==e)},addRevolutAllowedUser(){const e=this.formAddRevolutUser||"";e.length&&!this.formData.revolut_limits.allowed_users.includes(e)&&(this.formData.revolut_limits.allowed_users=[...this.formData.revolut_limits.allowed_users,e],this.formAddRevolutUser="")},removeRevolutAllowedUser(e){this.formData.revolut_limits.allowed_users=this.formData.revolut_limits.allowed_users.filter(t=>t!==e)},checkFiatProvider(e){LNbits.api.request("PUT",`/api/v1/fiat/check/${e}`).then(e=>{const t=e.data;Quasar.Notify.create({type:t.success?"positive":"warning",message:t.message,icon:null})}).catch(LNbits.utils.notifyApiError)},createRevolutWebhook(){const e=this.calculateWebhookUrl("revolut");this.formData.revolut_payment_webhook_url=e,this.formData.revolut_api_secret_key?this.isClearnetWebhookUrl(e)?(this.creatingRevolutWebhook=!0,LNbits.api.request("POST","/api/v1/fiat/revolut/webhook",null,{url:e,endpoint:this.formData.revolut_api_endpoint,api_secret_key:this.formData.revolut_api_secret_key,api_version:this.formData.revolut_api_version}).then(e=>{const t=e.data;this.formData.revolut_payment_webhook_url=t.url,this.formData.revolut_webhook_signing_secret=t.signing_secret,Quasar.Notify.create({type:"positive",message:`Revolut webhook ${t.already_exists?"already exists":"created"}${t.id?`: ${t.id}`:""}.`,icon:null})}).catch(LNbits.utils.notifyApiError).finally(()=>{this.creatingRevolutWebhook=!1})):this.notifyRevolutWebhookWarning("Revolut webhook URL must be a clearnet URL."):this.notifyRevolutWebhookWarning("Add your Revolut API secret key before creating a webhook.")}}}),window.app.component("lnbits-admin-exchange-providers",{props:["form-data"],template:"#lnbits-admin-exchange-providers",data:()=>({exchangeData:{selectedProvider:null,showTickerConversion:!1,convertFromTicker:null,convertToTicker:null},exchangesTable:{columns:[{name:"name",align:"left",label:"Exchange Name",field:"name",sortable:!0},{name:"api_url",align:"left",label:"URL",field:"api_url",sortable:!1},{name:"path",align:"left",label:"JSON Path",field:"path",sortable:!1},{name:"exclude_to",align:"left",label:"Exclude Currencies",field:"exclude_to",sortable:!1},{name:"ticker_conversion",align:"left",label:"Ticker Conversion",field:"ticker_conversion",sortable:!1}],pagination:{sortBy:"name",rowsPerPage:100,page:1,rowsNumber:100},search:null,hideEmpty:!0}}),mounted(){this.getExchangeRateHistory()},created(){const e=window.location.hash.replace("#","");"exchange_providers"===e&&this.showExchangeProvidersTab(e)},methods:{getDefaultSetting(e){LNbits.api.getDefaultSetting(e).then(t=>{this.formData[e]=t.data.default_value})},getExchangeRateHistory(){LNbits.api.request("GET","/api/v1/rate/history",this.g.user.wallets[0].inkey).then(e=>{this.initExchangeChart(e.data)}).catch(function(e){LNbits.utils.notifyApiError(e)})},showExchangeProvidersTab(e){"exchange_providers"===e&&this.getExchangeRateHistory()},addExchangeProvider(){this.formData.lnbits_exchange_rate_providers=[{name:"",api_url:"",path:"",exclude_to:[]},...this.formData.lnbits_exchange_rate_providers]},removeExchangeProvider(e){this.formData.lnbits_exchange_rate_providers=this.formData.lnbits_exchange_rate_providers.filter(t=>t!==e)},removeExchangeTickerConversion(e,t){e.ticker_conversion=e.ticker_conversion.filter(e=>e!==t),this.formData.touch=null},addExchangeTickerConversion(){this.exchangeData.selectedProvider&&(this.exchangeData.selectedProvider.ticker_conversion.push(`${this.exchangeData.convertFromTicker}:${this.exchangeData.convertToTicker}`),this.formData.touch=null,this.exchangeData.showTickerConversion=!1)},showTickerConversionDialog(e){this.exchangeData.convertFromTicker=null,this.exchangeData.convertToTicker=null,this.exchangeData.selectedProvider=e,this.exchangeData.showTickerConversion=!0},initExchangeChart(e){const t=e.map(e=>this.utils.formatTimestamp(e.timestamp,"HH:mm")),a=[...this.formData.lnbits_exchange_rate_providers,{name:"LNbits"}].map(t=>({label:t.name,data:e.map(e=>e.rates[t.name]),pointStyle:!0,borderWidth:"LNbits"===t.name?4:1,tension:.4}));this.exchangeRatesChart=new Chart(this.$refs.exchangeRatesChart.getContext("2d"),{type:"line",options:{plugins:{legend:{display:!1}}},data:{labels:t,datasets:a}})}}}),window.app.component("lnbits-admin-security",{props:["form-data"],template:"#lnbits-admin-security",data:()=>({logs:[],formBlockedIPs:"",serverlogEnabled:!1,nostrAcceptedUrl:"",formAllowedIPs:"",formCallbackUrlRule:""}),created(){},methods:{addAllowedIPs(){const e=this.formAllowedIPs.trim(),t=this.formData.lnbits_allowed_ips;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_allowed_ips=[...t,e],this.formAllowedIPs="")},removeAllowedIPs(e){const t=this.formData.lnbits_allowed_ips;this.formData.lnbits_allowed_ips=t.filter(t=>t!==e)},addBlockedIPs(){const e=this.formBlockedIPs.trim(),t=this.formData.lnbits_blocked_ips;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_blocked_ips=[...t,e],this.formBlockedIPs="")},removeBlockedIPs(e){const t=this.formData.lnbits_blocked_ips;this.formData.lnbits_blocked_ips=t.filter(t=>t!==e)},addCallbackUrlRule(){const e=this.formCallbackUrlRule.trim(),t=this.formData.lnbits_callback_url_rules;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_callback_url_rules=[...t,e],this.formCallbackUrlRule="")},removeCallbackUrlRule(e){const t=this.formData.lnbits_callback_url_rules;this.formData.lnbits_callback_url_rules=t.filter(t=>t!==e)},addNostrUrl(){const e=this.nostrAcceptedUrl.trim();this.removeNostrUrl(e),this.formData.nostr_absolute_request_urls.push(e),this.nostrAcceptedUrl=""},removeNostrUrl(e){this.formData.nostr_absolute_request_urls=this.formData.nostr_absolute_request_urls.filter(t=>t!==e)},async toggleServerLog(){if(this.serverlogEnabled=!this.serverlogEnabled,this.serverlogEnabled){const e="http:"!==location.protocol?"wss://":"ws://",t=await LNbits.utils.digestMessage(this.g.user.id),a=e+document.domain+":"+location.port+"/api/v1/ws/"+t;this.ws=new WebSocket(a),this.ws.addEventListener("message",async({data:e})=>{this.logs.push(e.toString());const t=this.$refs.logScroll;if(t){const e=t.getScrollTarget(),a=0;t.setScrollPosition(e.scrollHeight,a)}})}else this.ws.close()}}}),window.app.component("lnbits-admin-users",{props:["form-data"],template:"#lnbits-admin-users",data:()=>({formAddUser:"",formAddAdmin:"",formAddActivationCode:"",showReusableActivationCode:!1}),methods:{addAllowedUser(){let e=this.formAddUser,t=this.formData.lnbits_allowed_users;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_allowed_users=[...t,e],this.formAddUser="")},removeAllowedUser(e){let t=this.formData.lnbits_allowed_users;this.formData.lnbits_allowed_users=t.filter(t=>t!==e)},addAdminUser(){let e=this.formAddAdmin,t=this.formData.lnbits_admin_users;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_admin_users=[...t,e],this.formAddAdmin="")},removeAdminUser(e){let t=this.formData.lnbits_admin_users;this.formData.lnbits_admin_users=t.filter(t=>t!==e)},addOneTimeActivationCode(){const e=this.formAddActivationCode,t=this.formData.lnbits_register_one_time_activation_codes;e?.length&&!t.includes(e)&&(this.formData.lnbits_register_one_time_activation_codes=[...t,e],this.formAddActivationCode="")},removeOneTimeActivationCode(e){const t=this.formData.lnbits_register_one_time_activation_codes;this.formData.lnbits_register_one_time_activation_codes=t.filter(t=>t!==e)}}}),window.app.component("lnbits-admin-server",{props:["form-data"],template:"#lnbits-admin-server"}),window.app.component("lnbits-admin-extensions",{props:["form-data"],template:"#lnbits-admin-extensions",data:()=>({formAddExtensionsManifest:""}),methods:{addExtensionsManifest(){const e=this.formAddExtensionsManifest.trim(),t=this.formData.lnbits_extensions_manifests;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_extensions_manifests=[...t,e],this.formAddExtensionsManifest="")},removeExtensionsManifest(e){const t=this.formData.lnbits_extensions_manifests;this.formData.lnbits_extensions_manifests=t.filter(t=>t!==e)}}}),window.app.component("lnbits-admin-notifications",{props:["form-data"],template:"#lnbits-admin-notifications",data:()=>({nostrNotificationIdentifier:"",emailNotificationAddress:""}),methods:{sendTestEmail(){LNbits.api.request("GET","/admin/api/v1/testemail",this.g.user.wallets[0].adminkey).then(e=>{if("error"===e.data.status)throw new Error(e.data.message);this.$q.notify({message:"Test email sent!",color:"positive"})}).catch(e=>{this.$q.notify({message:e.message,color:"negative"})})},addNostrNotificationIdentifier(){const e=this.nostrNotificationIdentifier.trim(),t=this.formData.lnbits_nostr_notifications_identifiers;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_nostr_notifications_identifiers=[...t,e],this.nostrNotificationIdentifier="")},removeNostrNotificationIdentifier(e){const t=this.formData.lnbits_nostr_notifications_identifiers;this.formData.lnbits_nostr_notifications_identifiers=t.filter(t=>t!==e)},addEmailNotificationAddress(){const e=this.emailNotificationAddress.trim(),t=this.formData.lnbits_email_notifications_to_emails;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_email_notifications_to_emails=[...t,e],this.emailNotificationAddress="")},removeEmailNotificationAddress(e){const t=this.formData.lnbits_email_notifications_to_emails;this.formData.lnbits_email_notifications_to_emails=t.filter(t=>t!==e)}}}),window.app.component("lnbits-admin-site-customisation",{props:["form-data"],template:"#lnbits-admin-site-customisation",data:()=>({lnbits_theme_options:["classic","bitcoin","flamingo","cyber","freedom","mint","autumn","monochrome","salvador"],colors:["primary","secondary","accent","positive","negative","info","warning","red","yellow","orange"],reactionOptions:["none","confettiBothSides","confettiFireworks","confettiStars","confettiTop"],globalBorderOptions:["retro-border","hard-border","neon-border","no-border"]}),methods:{onBackgroundImageInput(e){const t=e.target.files[0];t&&this.uploadBackgroundImage(t),e.target.value=null},async uploadBackgroundImage(e){const t=new FormData;t.append("file",e);try{const{data:e}=await LNbits.api.request("POST","/api/v1/assets?public_asset=true",null,t,{headers:{"Content-Type":"multipart/form-data"}}),a=`${window.location.origin}/api/v1/assets/${e.id}/thumbnail`;this.formData.lnbits_default_bgimage=a,Quasar.Notify.create({type:"positive",message:"Background image uploaded.",icon:null})}catch(e){LNbits.utils.notifyApiError(e)}}}}),window.app.component("lnbits-admin-assets-config",{props:["form-data"],template:"#lnbits-admin-assets-config",data:()=>({newAllowedAssetMimeType:"",newNoLimitUser:""}),async created(){},methods:{addAllowedAssetMimeType(){this.newAllowedAssetMimeType&&(this.removeAllowedAssetMimeType(this.newAllowedAssetMimeType),this.formData.lnbits_assets_allowed_mime_types.push(this.newAllowedAssetMimeType),this.newAllowedAssetMimeType="",this.formData.touch=null)},removeAllowedAssetMimeType(e){const t=this.formData.lnbits_assets_allowed_mime_types.indexOf(e);-1!==t&&this.formData.lnbits_assets_allowed_mime_types.splice(t,1),this.formData.touch=null},addNewNoLimitUser(){this.newNoLimitUser&&(this.removeNoLimitUser(this.newNoLimitUser),this.formData.lnbits_assets_no_limit_users.push(this.newNoLimitUser),this.newNoLimitUser="",this.formData.touch=null)},removeNoLimitUser(e){e&&(this.formData.lnbits_assets_no_limit_users=this.formData.lnbits_assets_no_limit_users.filter(t=>t!==e),this.formData.touch=null)}}}),window.app.component("lnbits-admin-audit",{props:["form-data"],template:"#lnbits-admin-audit",data:()=>({formAddIncludePath:"",formAddExcludePath:"",formAddIncludeResponseCode:""}),methods:{addIncludePath(){if(""===this.formAddIncludePath)return;const e=this.formData.lnbits_audit_include_paths;e.includes(this.formAddIncludePath)||(this.formData.lnbits_audit_include_paths=[...e,this.formAddIncludePath]),this.formAddIncludePath=""},removeIncludePath(e){this.formData.lnbits_audit_include_paths=this.formData.lnbits_audit_include_paths.filter(t=>t!==e)},addExcludePath(){if(""===this.formAddExcludePath)return;const e=this.formData.lnbits_audit_exclude_paths;e.includes(this.formAddExcludePath)||(this.formData.lnbits_audit_exclude_paths=[...e,this.formAddExcludePath]),this.formAddExcludePath=""},removeExcludePath(e){this.formData.lnbits_audit_exclude_paths=this.formData.lnbits_audit_exclude_paths.filter(t=>t!==e)},addIncludeResponseCode(){if(""===this.formAddIncludeResponseCode)return;const e=this.formData.lnbits_audit_http_response_codes;e.includes(this.formAddIncludeResponseCode)||(this.formData.lnbits_audit_http_response_codes=[...e,this.formAddIncludeResponseCode]),this.formAddIncludeResponseCode=""},removeIncludeResponseCode(e){this.formData.lnbits_audit_http_response_codes=this.formData.lnbits_audit_http_response_codes.filter(t=>t!==e)}}}),window.app.component("lnbits-wallet-charts",{template:"#lnbits-wallet-charts",props:["paymentFilter","chartConfig"],data:()=>({debounceTimeoutValue:1337,debounceTimeout:null,chartData:[],chartDataPointCount:0,walletBalanceChart:null,walletBalanceInOut:null,walletPaymentInOut:null,colorPrimary:Quasar.colors.changeAlpha(Quasar.colors.getPaletteColor("primary"),.3),colorSecondary:Quasar.colors.changeAlpha(Quasar.colors.getPaletteColor("secondary"),.3),barOptions:{responsive:!0,maintainAspectRatio:!1,scales:{x:{stacked:!0},y:{stacked:!0}}}}),watch:{paymentFilter:{deep:!0,handler(){this.changeCharts()}},chartConfig:{deep:!0,handler(e){this.$q.localStorage.setItem("lnbits.wallets.chartConfig",e),this.changeCharts()}}},methods:{changeCharts(){this.debounceTimeout&&clearTimeout(this.debounceTimeout),this.debounceTimeout=setTimeout(async()=>{await this.fetchChartData(),this.drawCharts()},this.debounceTimeoutValue)},filterChartData(){const e=this.paymentFilter["time[ge]"]+"T00:00:00",t=this.paymentFilter["time[le]"]+"T23:59:59";let a=0,s=this.chartData.map(e=>void 0!==this.paymentFilter["amount[ge]"]?(a+=e.balance_in,{...e,balance:a,balance_out:0,count_out:0}):void 0!==this.paymentFilter["amount[le]"]?(a-=e.balance_out,{...e,balance:a,balance_in:0,count_in:0}):{...e});s=s.filter(a=>this.paymentFilter["time[ge]"]&&this.paymentFilter["time[le]"]?a.date>=e&&a.date<=t:this.paymentFilter["time[ge]"]?a.date>=e:!this.paymentFilter["time[le]"]||a.date<=t);const i=s.map(e=>new Date(e.date).toLocaleString("default",{month:"short",day:"numeric"}));return this.chartDataPointCount=s.length,{data:s,labels:i}},drawBalanceInOutChart(e,t){this.walletBalanceInOut&&this.walletBalanceInOut.destroy();const a=this.$refs.walletBalanceInOut;a&&(this.walletBalanceInOut=new Chart(a.getContext("2d"),{type:"bar",options:this.barOptions,data:{labels:t,datasets:[{label:"Balance In",borderRadius:5,data:e.map(e=>e.balance_in),backgroundColor:this.colorPrimary},{label:"Balance Out",borderRadius:5,data:e.map(e=>e.balance_out),backgroundColor:this.colorSecondary}]}}))},drawPaymentInOut(e,t){this.walletPaymentInOut&&this.walletPaymentInOut.destroy();const a=this.$refs.walletPaymentInOut;a&&(this.walletPaymentInOut=new Chart(a.getContext("2d"),{type:"bar",options:this.barOptions,data:{labels:t,datasets:[{label:"Payments In",data:e.map(e=>e.count_in),backgroundColor:this.colorPrimary},{label:"Payments Out",data:e.map(e=>-e.count_out),backgroundColor:this.colorSecondary}]}}))},drawBalanceChart(e,t){this.walletBalanceChart&&this.walletBalanceChart.destroy();const a=this.$refs.walletBalanceChart;a&&(this.walletBalanceChart=new Chart(a.getContext("2d"),{type:"line",options:{responsive:!0,maintainAspectRatio:!1},data:{labels:t,datasets:[{label:"Balance",data:e.map(e=>e.balance),pointStyle:!1,backgroundColor:this.colorPrimary,borderColor:this.colorPrimary,borderWidth:2,fill:!0,tension:.7,fill:1},{label:"Fees",data:e.map(e=>e.fee),pointStyle:!1,backgroundColor:this.colorSecondary,borderColor:this.colorSecondary,borderWidth:1,fill:!0,tension:.7,fill:1}]}}))},drawCharts(){const{data:e,labels:t}=this.filterChartData();this.chartConfig.showBalanceChart&&this.drawBalanceChart(e,t),this.chartConfig.showBalanceInOutChart&&this.drawBalanceInOutChart(e,t),this.chartConfig.showPaymentInOutChart&&this.drawPaymentInOut(e,t)},async fetchChartData(){try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/daily?wallet_id=${this.g.wallet.id}`);this.chartData=e}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}}},async created(){await this.fetchChartData(),this.drawCharts()}}),window.app.component("lnbits-wallet-api-docs",{template:"#lnbits-wallet-api-docs",methods:{resetKeys(){LNbits.utils.confirmDialog("Are you sure you want to reset your API keys?").onOk(()=>{LNbits.api.resetWalletKeys(this.g.wallet).then(e=>{const{id:t,adminkey:a,inkey:s}=e;this.g.wallet={...this.g.wallet,inkey:s,adminkey:a};const i=this.g.user.wallets.findIndex(e=>e.id===t);-1!==i&&(this.g.user.wallets[i]={...this.g.user.wallets[i],inkey:s,adminkey:a}),Quasar.Notify.create({timeout:3500,type:"positive",message:"API keys reset!"})}).catch(e=>{LNbits.utils.notifyApiError(e)})})}},data:()=>({origin:window.location.origin,inkeyHidden:!0,adminkeyHidden:!0,walletIdHidden:!0})}),window.app.component("lnbits-wallet-icon",{template:"#lnbits-wallet-icon",data:()=>({icon:{show:!1,data:{},colorOptions:["primary","purple","orange","green","brown","blue","red","pink"],options:["home","star","bolt","paid","savings","store","videocam","music_note","flight","train","directions_car","school","construction","science","sports_esports","sports_tennis","theaters","water","headset_mic","videogame_asset","person","group","pets","sunny","elderly","verified","snooze","mail","forum","shopping_cart","shopping_bag","attach_money","print_connect","dark_mode","light_mode","android","network_wifi","shield","fitness_center","lunch_dining"]}}),methods:{setSelectedIcon(e){this.icon.data.icon=e},setSelectedColor(e){this.icon.data.color=e},setIcon(){this.$emit("update-wallet",this.icon.data),this.icon.show=!1}}}),window.app.component("lnbits-wallet-new",{template:"#lnbits-wallet-new",data:()=>({walletTypes:[{label:"Lightning Wallet",value:"lightning"}],wallet:{name:"",sharedWalletId:""},showNewWalletDialog:!1}),watch:{"g.newWalletType"(e){null!==e&&(this.showNewWalletDialog=!0)},showNewWalletDialog(e){!0!==e&&this.reset()}},computed:{isLightning(){return"lightning"===this.g.newWalletType},isLightningShared(){return"lightning-shared"===this.g.newWalletType},inviteWalletOptions(){return(this.g.user?.extra?.wallet_invite_requests||[]).map(e=>({label:`${e.to_wallet_name} (from ${e.from_user_name})`,value:e.to_wallet_id}))}},methods:{reset(){this.showNewWalletDialog=!1,this.g.newWalletType=null,this.wallet={name:"",sharedWalletId:""}},async submitRejectWalletInvitation(){try{const e=this.g.user.extra.wallet_invite_requests||[],t=e.find(e=>e.to_wallet_id===this.wallet.sharedWalletId);if(!t)return void Quasar.Notify.create({message:"Cannot find invitation for the selected wallet.",type:"warning"});await LNbits.api.request("DELETE",`/api/v1/wallet/share/invite/${t.request_id}`,this.g.wallet.adminkey),Quasar.Notify.create({message:"Invitation rejected.",type:"positive"}),this.g.user.extra.wallet_invite_requests=e.filter(e=>e.request_id!==t.request_id)}catch(e){LNbits.utils.notifyApiError(e)}},submitAddWallet(){const e=this.wallet;"lightning"!==this.g.newWalletType||e.name?"lightning-shared"!==this.g.newWalletType||e.sharedWalletId?LNbits.api.createWallet(e.name,this.g.newWalletType,{shared_wallet_id:e.sharedWalletId}).then(e=>{this.$q.notify({message:"Wallet created successfully",color:"positive"}),this.reset(),this.g.user.wallets.push(LNbits.map.wallet(e.data)),this.g.lastWalletId=e.data.id,this.$router.push(`/wallet/${e.data.id}`)}).catch(LNbits.utils.notifyApiError):this.$q.notify({message:"Missing a shared wallet ID",color:"warning"}):this.$q.notify({message:"Please enter a name for the wallet",color:"warning"})}},created(){this.g.user?.extra?.wallet_invite_requests?.length&&this.walletTypes.push({label:`Lightning Wallet (Share Invite: ${this.g.user.extra.wallet_invite_requests.length})`,value:"lightning-shared"})}}),window.app.component("lnbits-wallet-share",{template:"#lnbits-wallet-share",computed:{walletApprovedShares(){return this.g.wallet.extra.shared_with.filter(e=>"approved"===e.status)},walletPendingRequests(){return this.g.wallet.extra.shared_with.filter(e=>"request_access"===e.status)},walletPendingInvites(){return this.g.wallet.extra.shared_with.filter(e=>"invite_sent"===e.status)}},data:()=>({permissionOptions:[{label:"View",value:"view-payments"},{label:"Receive",value:"receive-payments"},{label:"Send",value:"send-payments"}],walletShareInvite:{username:"",permissions:[]}}),methods:{async updateSharePermissions(e){try{const{data:t}=await LNbits.api.request("PUT","/api/v1/wallet/share",this.g.wallet.adminkey,e);Object.assign(e,t),Quasar.Notify.create({message:"Wallet permission updated.",type:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}},async inviteUserToWallet(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/wallet/share/invite",this.g.wallet.adminkey,{...this.walletShareInvite,status:"invite_sent",wallet_id:this.g.wallet.id});this.g.wallet.extra.shared_with.push(e),this.walletShareInvite={username:"",permissions:[]},Quasar.Notify.create({message:"User invited to wallet.",type:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}},deleteSharePermission(e){LNbits.utils.confirmDialog("Are you sure you want to remove this share permission?").onOk(async()=>{try{await LNbits.api.request("DELETE",`/api/v1/wallet/share/${e.request_id}`,this.g.wallet.adminkey),this.g.wallet.extra.shared_with=this.g.wallet.extra.shared_with.filter(t=>t.wallet_id!==e.wallet_id),Quasar.Notify.create({message:"Wallet permission deleted.",type:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}})}}}),window.app.component("lnbits-wallet-paylinks",{template:"#lnbits-wallet-paylinks",data:()=>({storedPaylinks:[]}),watch:{"g.wallet"(e){this.storedPaylinks=e.storedPaylinks??[]}},created(){this.storedPaylinks=this.g.wallet.storedPaylinks},methods:{updatePaylinks(){LNbits.api.request("PUT",`/api/v1/wallet/stored_paylinks/${this.g.wallet.id}`,this.g.wallet.adminkey,{links:this.storedPaylinks}).then(()=>{this.$q.notify({message:"Paylinks updated.",type:"positive",timeout:3500})}).catch(e=>{LNbits.utils.notifyApiError(e)})},sendToPaylink(e){this.$emit("send-lnurl",e)},editPaylink(){this.$nextTick(()=>{this.updatePaylinks()})},deletePaylink(e){const t=[];this.storedPaylinks.forEach(a=>{a.lnurl!==e&&t.push(a)}),this.storedPaylinks=t,this.updatePaylinks()}}}),window.app.component("lnbits-wallet-extra",{template:"#lnbits-wallet-extra",props:["chartConfig"],computed:{exportUrl(){return`${window.location.origin}/wallet?usr=${this.g.user.id}&wal=${this.g.wallet.id}`}},methods:{handleSendLnurl(e){this.$emit("send-lnurl",e)},updateWallet(e){this.$emit("update-wallet",e)},handleFiatTracking(){this.g.fiatTracking=!this.g.fiatTracking,this.g.fiatTracking?(this.updateWallet({currency:this.g.wallet.currency}),this.updateFiatBalance()):(this.g.isFiatPriority=!1,this.g.wallet.currency="",this.updateWallet({currency:""}))},deleteWallet(){LNbits.utils.confirmDialog("Are you sure you want to delete this wallet?").onOk(()=>{LNbits.api.deleteWallet(this.g.wallet).then(()=>{this.g.user.wallets=this.g.user.wallets.filter(e=>e.id!==this.g.wallet.id),this.g.lastActiveWallet=this.g.user.wallets[0].id,this.$router.push(`/wallet/${this.g.lastActiveWallet}`),Quasar.Notify.create({timeout:3e3,message:"Wallet deleted!",spinner:!0})}).catch(e=>{LNbits.utils.notifyApiError(e)})})},updateFiatBalance(){this.$q.localStorage.getItem("lnbits.exchangeRate."+this.g.wallet.currency)&&(this.g.exchangeRate=this.$q.localStorage.getItem("lnbits.exchangeRate."+this.g.wallet.currency),this.g.fiatBalance=this.g.exchangeRate/1e8*this.g.wallet.sat),LNbits.api.request("GET","/api/v1/rate/"+this.g.wallet.currency,null).then(e=>{this.g.fiatBalance=e.data.price/1e8*this.g.wallet.sat,this.g.exchangeRate=e.data.price.toFixed(2),this.g.fiatTracking=!0,this.$q.localStorage.set("lnbits.exchangeRate."+this.g.wallet.currency,this.g.exchangeRate),this.g.exchangeRate<=0&&(this.g.fiatTracking=!1,this.g.isFiatPriority=!1)}).catch(e=>console.error(e))}},created(){""!==this.g.wallet.currency&&this.g.isSatsDenomination?(this.g.fiatTracking=!0,this.updateFiatBalance()):this.g.fiatTracking=!1}}),window.app.component("lnbits-home-logos",{template:"#lnbits-home-logos",data:()=>({logos:[{href:"https://github.com/ElementsProject/lightning",lightSrc:"/static/images/clnl.png",darkSrc:"/static/images/cln.png"},{href:"https://github.com/lightningnetwork/lnd",lightSrc:"/static/images/lnd.png",darkSrc:"/static/images/lnd.png"},{href:"https://opennode.com",lightSrc:"/static/images/opennodel.png",darkSrc:"/static/images/opennode.png"},{href:"https://lnpay.co/",lightSrc:"/static/images/lnpayl.png",darkSrc:"/static/images/lnpay.png"},{href:"https://github.com/rootzoll/raspiblitz",lightSrc:"/static/images/blitzl.png",darkSrc:"/static/images/blitz.png"},{href:"https://start9.com/",lightSrc:"/static/images/start9l.png",darkSrc:"/static/images/start9.png"},{href:"https://getumbrel.com/",lightSrc:"/static/images/umbrell.png",darkSrc:"/static/images/umbrel.png"},{href:"https://mynodebtc.com",lightSrc:"/static/images/mynodel.png",darkSrc:"/static/images/mynode.png"},{href:"https://github.com/shesek/spark-wallet",lightSrc:"/static/images/sparkl.png",darkSrc:"/static/images/spark.png"},{href:"https://voltage.cloud",lightSrc:"/static/images/voltagel.png",darkSrc:"/static/images/voltage.png"},{href:"https://breez.technology/sdk/",lightSrc:"/static/images/breezl.png",darkSrc:"/static/images/breez.png"},{href:"https://blockstream.com/lightning/greenlight/",lightSrc:"/static/images/greenlightl.png",darkSrc:"/static/images/greenlight.png"},{href:"https://getalby.com",lightSrc:"/static/images/albyl.png",darkSrc:"/static/images/alby.png"},{href:"https://zbd.gg",lightSrc:"/static/images/zbdl.png",darkSrc:"/static/images/zbd.png"},{href:"https://phoenix.acinq.co/server",lightSrc:"/static/images/phoenixdl.png",darkSrc:"/static/images/phoenixd.png"},{href:"https://boltz.exchange/",lightSrc:"/static/images/boltzl.svg",darkSrc:"/static/images/boltz.svg"},{href:"https://www.blink.sv/",lightSrc:"/static/images/blink_logol.png",darkSrc:"/static/images/blink_logo.png"}]}),computed:{showLogos(){return this.g.isSatsDenomination&&"LNbits"==this.g.settings.siteTitle&&1==this.g.settings.showHomePageElements}}}),window.app.component("lnbits-error",{template:"#lnbits-error",props:["dynamic","code","message"],computed:{isExtension(){return 403==this.code&&(!!this.message.startsWith("Extension ")||void 0)}},methods:{goBack(){window.history.back()},goHome(){window.location="/"},goToWallet(){this.dynamic?this.$router.push("/wallet"):window.location="/wallet"},goToExtension(){const e=`/extensions#${this.message.match(/'([^']+)'/)[1]}`;this.dynamic?this.$router.push(e):window.location=e},async logOut(){try{await LNbits.api.logout(),window.location="/"}catch(e){LNbits.utils.notifyApiError(e)}}},async created(){if(!this.dynamic&&401==this.code)return console.warn(`Unauthorized: ${this.errorMessage}`),void this.logOut()}}),window.app.component("lnbits-qrcode",{template:"#lnbits-qrcode",components:{QrcodeVue:QrcodeVue.default},props:{value:{type:String,required:!0},nfc:{type:Boolean,default:!1},print:{type:Boolean,default:!1},showButtons:{type:Boolean,default:!0},href:{type:String,default:""},margin:{type:Number,default:3},maxWidth:{type:Number,default:450},logo:{type:String,default:window.g.settings.qrLogo||null}},data:()=>({nfcTagWriting:!1,nfcSupported:"undefined"!=typeof NDEFReader}),methods:{printQrCode(){const e=this.$refs.qrCode.$el.outerHTML,t=window.open("","_blank");t.document.write(`\n \n
\n