feat: add dynamic errorpage (#3602)
This commit is contained in:
parent
89cabda123
commit
eefaf3c50c
20 changed files with 143 additions and 117 deletions
|
|
@ -221,6 +221,7 @@ async def index(
|
||||||
|
|
||||||
|
|
||||||
@generic_router.get("/")
|
@generic_router.get("/")
|
||||||
|
@generic_router.get("/error")
|
||||||
@generic_router.get("/node/public")
|
@generic_router.get("/node/public")
|
||||||
@generic_router.get("/first_install", dependencies=[Depends(check_first_install)])
|
@generic_router.get("/first_install", dependencies=[Depends(check_first_install)])
|
||||||
async def index_public(request: Request) -> HTMLResponse:
|
async def index_public(request: Request) -> HTMLResponse:
|
||||||
|
|
|
||||||
2
lnbits/static/bundle-components.min.js
vendored
2
lnbits/static/bundle-components.min.js
vendored
File diff suppressed because one or more lines are too long
2
lnbits/static/bundle.min.css
vendored
2
lnbits/static/bundle.min.css
vendored
File diff suppressed because one or more lines are too long
2
lnbits/static/bundle.min.js
vendored
2
lnbits/static/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -454,3 +454,12 @@ video {
|
||||||
width: 90% !important;
|
width: 90% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.error-code {
|
||||||
|
font-size: clamp(15vh, 20vw, 30vh);
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
font-size: clamp(1.5rem, 3vw, 3.75rem);
|
||||||
|
font-weight: 300;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
|
||||||
53
lnbits/static/js/components/lnbits-error.js
Normal file
53
lnbits/static/js/components/lnbits-error.js
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
window.app.component('lnbits-error', {
|
||||||
|
template: '#lnbits-error',
|
||||||
|
mixins: [window.windowMixin],
|
||||||
|
props: ['dynamic', 'code', 'message'],
|
||||||
|
computed: {
|
||||||
|
isExtension() {
|
||||||
|
if (this.code != 403) return false
|
||||||
|
if (this.message.startsWith('Extension ')) return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
goBack() {
|
||||||
|
window.history.back()
|
||||||
|
},
|
||||||
|
goHome() {
|
||||||
|
window.location = '/'
|
||||||
|
},
|
||||||
|
goToWallet() {
|
||||||
|
if (this.dynamic) {
|
||||||
|
this.$router.push('/wallet')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.location = '/wallet'
|
||||||
|
},
|
||||||
|
goToExtension() {
|
||||||
|
const extension = this.message.match(/'([^']+)'/)[1]
|
||||||
|
const url = `/extensions#${extension}`
|
||||||
|
if (this.dynamic) {
|
||||||
|
this.$router.push(url)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.location = url
|
||||||
|
},
|
||||||
|
async logOut() {
|
||||||
|
try {
|
||||||
|
await LNbits.api.logout()
|
||||||
|
window.location = '/'
|
||||||
|
} catch (e) {
|
||||||
|
LNbits.utils.notifyApiError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
// check if we have error from error.html
|
||||||
|
if (!this.dynamic) {
|
||||||
|
if (this.code == 401) {
|
||||||
|
console.warn(`Unauthorized: ${this.errorMessage}`)
|
||||||
|
this.logOut()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
@ -9,6 +9,8 @@ const localStore = (key, defaultValue) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
window.g = Vue.reactive({
|
window.g = Vue.reactive({
|
||||||
|
errorCode: null,
|
||||||
|
errorMessage: null,
|
||||||
isUserAuthorized: !!Quasar.Cookies.get('is_lnbits_user_authorized'),
|
isUserAuthorized: !!Quasar.Cookies.get('is_lnbits_user_authorized'),
|
||||||
offline: !navigator.onLine,
|
offline: !navigator.onLine,
|
||||||
hasCamera: false,
|
hasCamera: false,
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,11 @@ const routes = [
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'PageHome',
|
name: 'PageHome',
|
||||||
component: PageHome
|
component: PageHome
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/error',
|
||||||
|
name: 'PageError',
|
||||||
|
component: PageError
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
4
lnbits/static/js/pages/error.js
Normal file
4
lnbits/static/js/pages/error.js
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
window.PageError = {
|
||||||
|
template: '#page-error',
|
||||||
|
mixins: [window.windowMixin]
|
||||||
|
}
|
||||||
|
|
@ -604,16 +604,17 @@ window.PageWallet = {
|
||||||
this.decodeRequest()
|
this.decodeRequest()
|
||||||
this.parse.show = true
|
this.parse.show = true
|
||||||
}
|
}
|
||||||
let wallet = g.user.wallets.find(w => w.id === this.$route.params.id)
|
const wallet = g.user.wallets.find(w => w.id === this.$route.params.id)
|
||||||
if (!wallet) {
|
if (wallet) {
|
||||||
const walletId = g.lastActiveWallet || g.user.wallets[0].id
|
this.g.wallet = wallet
|
||||||
wallet = g.user.wallets.find(w => w.id === walletId)
|
this.g.lastActiveWallet = wallet.id
|
||||||
// TODO: should show PageError(404) if wallet not found
|
this.$q.localStorage.setItem('lnbits.lastActiveWallet', wallet.id)
|
||||||
|
this.$router.replace(`/wallet/${wallet.id}`)
|
||||||
|
} else {
|
||||||
|
this.g.errorCode = 404
|
||||||
|
this.g.errorMessage = 'Wallet not found.'
|
||||||
|
this.$router.push('/error')
|
||||||
}
|
}
|
||||||
this.g.wallet = wallet
|
|
||||||
this.g.lastActiveWallet = wallet.id
|
|
||||||
this.$q.localStorage.setItem('lnbits.lastActiveWallet', wallet.id)
|
|
||||||
this.$router.replace(`/wallet/${wallet.id}`)
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'g.updatePaymentsHash'() {
|
'g.updatePaymentsHash'() {
|
||||||
|
|
|
||||||
|
|
@ -197,3 +197,12 @@ video {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-code {
|
||||||
|
font-size: clamp(15vh, 20vw, 30vh);
|
||||||
|
}
|
||||||
|
.error-message {
|
||||||
|
font-size: clamp(1.5rem, calc(1.5 / 10 * 20vw), 3.75rem);
|
||||||
|
font-weight: 300;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
"js/bolt11-decoder.js"
|
"js/bolt11-decoder.js"
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
|
"js/pages/error.js",
|
||||||
"js/pages/home.js",
|
"js/pages/home.js",
|
||||||
"js/pages/extensions_builder.js",
|
"js/pages/extensions_builder.js",
|
||||||
"js/pages/extensions.js",
|
"js/pages/extensions.js",
|
||||||
|
|
@ -75,6 +76,7 @@
|
||||||
"js/components/lnbits-wallet-paylinks.js",
|
"js/components/lnbits-wallet-paylinks.js",
|
||||||
"js/components/lnbits-wallet-extra.js",
|
"js/components/lnbits-wallet-extra.js",
|
||||||
"js/components/lnbits-home-logos.js",
|
"js/components/lnbits-home-logos.js",
|
||||||
|
"js/components/lnbits-error.js",
|
||||||
"js/components/lnbits-qrcode.js",
|
"js/components/lnbits-qrcode.js",
|
||||||
"js/components/lnbits-qrcode-lnurl.js",
|
"js/components/lnbits-qrcode-lnurl.js",
|
||||||
"js/components/lnbits-disclaimer.js",
|
"js/components/lnbits-disclaimer.js",
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ include('components/lnbits-wallet-api-docs.vue') %} {%
|
||||||
include('components/lnbits-wallet-share.vue') %} {%
|
include('components/lnbits-wallet-share.vue') %} {%
|
||||||
include('components/lnbits-wallet-charts.vue') %} {%
|
include('components/lnbits-wallet-charts.vue') %} {%
|
||||||
include('components/lnbits-wallet-paylinks.vue') %} {%
|
include('components/lnbits-wallet-paylinks.vue') %} {%
|
||||||
include('components/lnbits-wallet-extra.vue') %}
|
include('components/lnbits-wallet-extra.vue') %} {%
|
||||||
|
include('components/lnbits-error.vue') %}
|
||||||
|
|
||||||
<template id="lnbits-manage">
|
<template id="lnbits-manage">
|
||||||
<q-list v-if="g.user" dense class="lnbits-drawer__q-list">
|
<q-list v-if="g.user" dense class="lnbits-drawer__q-list">
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
flat
|
flat
|
||||||
:icon="g.walletFlip ? 'view_list' : 'view_column'"
|
:icon="g.walletFlip ? 'view_list' : 'view_column'"
|
||||||
color="grey"
|
color="grey"
|
||||||
class=""
|
|
||||||
@click="g.walletFlip = !g.walletFlip"
|
@click="g.walletFlip = !g.walletFlip"
|
||||||
>
|
>
|
||||||
<q-tooltip
|
<q-tooltip
|
||||||
|
|
|
||||||
25
lnbits/templates/components/lnbits-error.vue
Normal file
25
lnbits/templates/components/lnbits-error.vue
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<template id="lnbits-error">
|
||||||
|
<div class="text-center q-pa-md flex flex-center">
|
||||||
|
<div>
|
||||||
|
<div class="error-code" v-text="code"></div>
|
||||||
|
<div class="error-message" v-text="message"></div>
|
||||||
|
<div class="q-mx-auto q-mt-lg justify-center" style="width: max-content">
|
||||||
|
<q-btn
|
||||||
|
v-if="isExtension"
|
||||||
|
color="primary"
|
||||||
|
@click="goToExtension()"
|
||||||
|
label="Go To Extension"
|
||||||
|
></q-btn>
|
||||||
|
<q-btn
|
||||||
|
v-else-if="g.isUserAuthorized"
|
||||||
|
color="primary"
|
||||||
|
@click="goToWallet()"
|
||||||
|
label="Go to Wallet"
|
||||||
|
></q-btn>
|
||||||
|
<q-btn v-else color="primary" @click="goBack()" label="Go Back"></q-btn>
|
||||||
|
<span class="q-mx-md">OR</span>
|
||||||
|
<q-btn color="secondary" @click="goHome()" label="Go Home"></q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -1,102 +1,5 @@
|
||||||
{% extends "public.html" %} {% block page_container %}
|
{% extends "public.html" %} {% from "macros.jinja" import window_vars with
|
||||||
<q-page-container>
|
context %} {% block scripts %} {{ window_vars() }} {% endblock %} {% block
|
||||||
<q-page
|
page_container %}
|
||||||
class="q-px-md q-py-lg content-center"
|
<lnbits-error code="{{ status_code }}" message="{{ message }}"></lnbits-error>
|
||||||
:class="{'q-px-lg': $q.screen.gt.xs}"
|
|
||||||
>
|
|
||||||
{% block page %}
|
|
||||||
<div class="text-center q-pa-md flex flex-center">
|
|
||||||
<div v-if="statusCode">
|
|
||||||
<div class="error-code" v-text="statusCode"></div>
|
|
||||||
|
|
||||||
<div class="error-message" v-text="message"></div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="q-mx-auto q-mt-lg justify-center"
|
|
||||||
style="width: max-content"
|
|
||||||
>
|
|
||||||
<q-btn
|
|
||||||
v-if="isExtension"
|
|
||||||
color="primary"
|
|
||||||
@click="goToExtension"
|
|
||||||
label="Go To Extension"
|
|
||||||
class="q-mb-lg full-width"
|
|
||||||
></q-btn>
|
|
||||||
<br />
|
|
||||||
<q-btn color="primary" href="/" label="Go Home"></q-btn>
|
|
||||||
<span class="q-mx-md">OR</span>
|
|
||||||
<q-btn color="primary" @click="goBack" label="Go Back"></q-btn>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
</q-page>
|
|
||||||
</q-page-container>
|
|
||||||
{% endblock %} {% block scripts %}
|
|
||||||
<style>
|
|
||||||
.error-code {
|
|
||||||
font-size: clamp(15vh, 20vw, 30vh);
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-message {
|
|
||||||
font-size: clamp(1.5rem, calc(1.5 / 10 * 20vw), 3.75rem);
|
|
||||||
font-weight: 300;
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
window.app = Vue.createApp({
|
|
||||||
el: '#vue',
|
|
||||||
mixins: [window.windowMixin],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
err: null,
|
|
||||||
statusCode: null,
|
|
||||||
message: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
goBack: function () {
|
|
||||||
window.history.back()
|
|
||||||
},
|
|
||||||
goHome: function () {
|
|
||||||
window.location.href = '/'
|
|
||||||
},
|
|
||||||
goToExtension() {
|
|
||||||
window.location.href = `/extensions#${this.extension}`
|
|
||||||
},
|
|
||||||
async logOut() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
await LNbits.api.logout()
|
|
||||||
window.location = '/'
|
|
||||||
} catch (e) {
|
|
||||||
LNbits.utils.notifyApiError(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isExtension() {
|
|
||||||
if (this.statusCode != 403) return false
|
|
||||||
if (this.message.startsWith('Extension ')) return true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async created() {
|
|
||||||
this.err = '{{ err }}'
|
|
||||||
const statusCode = '{{ status_code }}' || 404
|
|
||||||
this.message = String({{ message | tojson }}) || 'Page not found'
|
|
||||||
if (statusCode == 401) {
|
|
||||||
console.warn(`Unauthorized: ${this.message}`)
|
|
||||||
this.logOut()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.statusCode = statusCode
|
|
||||||
|
|
||||||
if (this.isExtension) {
|
|
||||||
this.extension = this.message.match(/'([^']+)'/)[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,5 @@ include('pages/audit.vue') %} {% include('pages/wallets.vue') %} {%
|
||||||
include('pages/users.vue') %} {% include('pages/admin.vue') %} {%
|
include('pages/users.vue') %} {% include('pages/admin.vue') %} {%
|
||||||
include('pages/account.vue') %} {% include('pages/extensions_builder.vue') %} {%
|
include('pages/account.vue') %} {% include('pages/extensions_builder.vue') %} {%
|
||||||
include('pages/extensions.vue') %} {% include('pages/first-install.vue') %} {%
|
include('pages/extensions.vue') %} {% include('pages/first-install.vue') %} {%
|
||||||
include('pages/home.vue') %} {% include('pages/wallet.vue') %}
|
include('pages/home.vue') %} {% include('pages/wallet.vue') %} {%
|
||||||
|
include('pages/error.vue') %}
|
||||||
|
|
|
||||||
9
lnbits/templates/pages/error.vue
Normal file
9
lnbits/templates/pages/error.vue
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<template id="page-error">
|
||||||
|
<div id="page-error">
|
||||||
|
<lnbits-error
|
||||||
|
:dynamic="true"
|
||||||
|
:code="g.errorCode"
|
||||||
|
:message="g.errorMessage"
|
||||||
|
></lnbits-error>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template id="page-wallet">
|
<template id="page-wallet">
|
||||||
<div class="row q-col-gutter-md" style="margin-bottom: 6rem">
|
<div v-if="g.wallet" class="row q-col-gutter-md" style="margin-bottom: 6rem">
|
||||||
<div class="col-12 col-md-7 q-gutter-y-md wallet-wrapper">
|
<div class="col-12 col-md-7 q-gutter-y-md wallet-wrapper">
|
||||||
<q-card class="wallet-card">
|
<q-card class="wallet-card">
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@
|
||||||
"js/bolt11-decoder.js"
|
"js/bolt11-decoder.js"
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
|
"js/pages/error.js",
|
||||||
"js/pages/home.js",
|
"js/pages/home.js",
|
||||||
"js/pages/extensions_builder.js",
|
"js/pages/extensions_builder.js",
|
||||||
"js/pages/extensions.js",
|
"js/pages/extensions.js",
|
||||||
|
|
@ -127,6 +128,7 @@
|
||||||
"js/components/lnbits-wallet-paylinks.js",
|
"js/components/lnbits-wallet-paylinks.js",
|
||||||
"js/components/lnbits-wallet-extra.js",
|
"js/components/lnbits-wallet-extra.js",
|
||||||
"js/components/lnbits-home-logos.js",
|
"js/components/lnbits-home-logos.js",
|
||||||
|
"js/components/lnbits-error.js",
|
||||||
"js/components/lnbits-qrcode.js",
|
"js/components/lnbits-qrcode.js",
|
||||||
"js/components/lnbits-qrcode-lnurl.js",
|
"js/components/lnbits-qrcode-lnurl.js",
|
||||||
"js/components/lnbits-disclaimer.js",
|
"js/components/lnbits-disclaimer.js",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue